0
点赞
收藏
分享

微信扫一扫

左程云基础班——二叉树

J简文 2022-03-12 阅读 88
javaleetcode

左程云基础班——二叉树

1. 遍历二叉树

二叉树结点:

public class Node {
    public int value;
    public Node left;
    public Node right;

    public Node(int value) {
        this.value = value;
    }
}

1)前序遍历

	public static void preOrderRecur(Node head) {
        if (head == null) {
            return;
        }
        
        System.out.print(head.value + " ");
        
        preOrderRecur(head.left);
        preOrderRecur(head.right);
    }
    
    public static void preOrderUnRecur(Node head) {
        if (head != null) {
        	//入栈顺序根右左
            Stack<Node> stack = new Stack<>();
            stack.push(head);
            while (!stack.isEmpty()) {
                head = stack.pop();
                
                System.out.print(head.value + " ");
                
                if (head.right != null) {
                    stack.push(head.right);
                }
                if (head.left != null) {
                    stack.push(head.left);
                }
            }
        }
    }

2)后序遍历

	public static void postOrderRecur(Node head) {
        if (head == null) {
            return;
        }
        postOrderRecur(head.left);
        postOrderRecur(head.right);
        
        System.out.print(head.value + " ");
    }
    //入栈顺序根左右,逆序输出
    public static void postOrderUnRrecur(Node head) {
        if (head != null) {
            Stack<Node> stack = new Stack<>();
            Stack<Node> res = new Stack<>();
            stack.push(head);
            while (!stack.isEmpty()) {
                head = stack.pop();
                res.push(head);
                if (head.left != null) {
                    stack.push(head.left);
                }
                if (head.right != null) {
                    stack.push(head.right);
                }
            }
            while (!res.isEmpty()) {
                
                System.out.print(res.pop().value + " ");
                
            }
        }
    }

3)中序遍历

	public static void inOrderRecur(Node head) {
        if (head == null) {
            return;
        }
        inOrderRecur(head.left);
        
        System.out.print(head.value + " ");
        
        inOrderRecur(head.right);
    }
    //左子树全部入栈
    public static void inOrderUnRecur(Node head) {
        if (head != null) {
            Stack<Node> stack = new Stack<>();
            while (!stack.isEmpty() || head != null) {
                if (head != null) {
                    stack.push(head);
                    head = head.left;
                } else {
                    head = stack.pop();
                    
                    System.out.print(head.value + " ");
                    
                    head = head.right;
                }
            }
        }
    }

4)宽度遍历(最大宽度)

public static int WildTravel(Node head) {
        if (head != null) {
            LinkedList<Node> queue = new LinkedList<>();
            
            HashMap hashMap = new HashMap<Node, Integer>();
            hashMap.put(head, 1);
            int curlevel = 0;
            int levelNodes = 0;
            int maxNodes = 0;
            
            queue.add(head);
            while (!queue.isEmpty()) {
                head = queue.poll();

//                System.out.print(head.value + " ");
                
                if ((int)hashMap.get(head) > curlevel) {
                    curlevel = (int)hashMap.get(head);
                    levelNodes = 1;
                }
                else {
                    levelNodes++;
                }
                maxNodes = Math.max(maxNodes, levelNodes);

                if (head.left != null) {
                    hashMap.put(head.left, (int)hashMap.get(head) + 1);
                    queue.add(head.left);
                }
                if (head.right != null) {
                    hashMap.put(head.right, (int)hashMap.get(head) + 1);
                    queue.add(head.right);
                }
            }
            return maxNodes;
        }
        return 0;
    }

2. 判断树结构

树形DP的套路方法:

1)判断二叉查找树

递归实现:

    public static int preValue = Integer.MIN_VALUE;
    public static boolean checkBST1(Node head) {
        if (head == null) {
            return true;
        }
        boolean left = checkBST1(head.left);
        if (left != true) {
            return false;
        }
        if (head.value < preValue) {
            return false;
        }
        else {
            preValue = head.value;
        }
        return checkBST1(head.right);
    }

非递归实现:

	public static boolean checkBST2(Node head) {
        if (head != null) {
            int preValue = Integer.MIN_VALUE;
            Stack<Node> stack = new Stack<>();
            while (!stack.isEmpty() || head != null) {
                if (head != null) {
                    stack.push(head);
                    head = head.left;
                } else {
                    head = stack.pop();
                    
                    if (head.value < preValue) {
                        return false;
                    }
                    else {
                        preValue = head.value;
                    }
                    
                    head = head.right;
                }
            }
        }
        return true;
    }

套路实现:

	public static boolean checkBST3(Node head) {
        bData avData = chBST(head);
        return avData.isBST;
    }
	
    private static class bData {
        //每个结点返回三个信息
        public boolean isBST;
        public int max;
        public int min;

        public bData(boolean isBST, int max, int min) {
            this.isBST = isBST;
            this.max = max;
            this.min = min;
        }
    }

    public static bData chBST(Node head) {
        //边界信息不好确定,返回空
        //确定自己信息时再具体判断
        if (head == null) {
            return null;
        }
        
        bData left = chBST(head.left);
        bData right = chBST(head.right);

        int min = head.value;
        int max = head.value;
        if (left != null) {
            min = Math.min(min, left.min);
            max = Math.max(max, left.max);
        }
        if (right != null) {
            min = Math.min(min, right.min);
            max = Math.max(max, right.max);
        }
        
        boolean isBST = true;
        if (left != null && (!left.isBST || left.min > head.value)) {
            isBST = false;
        }
        if (right != null && (!right.isBST || right.max < head.value)) {
            isBST = false;
        }
        
        return new bData(isBST, max, min);
    }

2). 判断完全二叉树

public static boolean checkCBT(Node head) {
        if (head != null) {
            boolean leaf = false;//表示以后的结点都是叶结点
            LinkedList<Node> queue = new LinkedList<>();
            queue.add(head);
            //基于宽度遍历
            while (!queue.isEmpty()) {
                head = queue.poll();
                
                if (
                        (head.left == null && head.right != null)
                        || (leaf == true && (head.left != null || head.right != null))
                ) {
                    return false;
                }

                if (head.left != null) {
                    queue.add(head.left);
                }
                if (head.right != null) {
                    queue.add(head.right);
                }
                //此结点右树为空,以后都是叶结点
                else {
                    leaf = true;
                }
            }
        }
        return true;
    }

3). 判断满二叉树

	public static boolean checkFBT(Node head) {
        fData c = prosses(head);
        if (c.nodes == (1 << c.height) - 1)
            return true;
        else
            return false;
    }

    private  static class fData{
        public int height;
        public int nodes;

        public fData(int height, int nodes) {
            this.height = height;
            this.nodes = nodes;
        }
    }

    public static fData prosses(Node head) {
        //套路解法
        if (head == null) {
            return new fData(0,0);
        }
        
        fData leftData = prosses(head.left);
        fData rightData = prosses(head.right);
        int height = Math.max(leftData.height, rightData.height) + 1;
        int nodes = leftData.nodes + rightData.nodes + 1;
        
        return new fData(height, nodes);
    }

3. 练习题

1). 寻找最近的公共父节点

	public static Node seekRoot(Node head, Node o1, Node o2) {
        HashMap<Node, Node> root = new HashMap<>();
        root.put(head, head);
        storeRoot(head, root);
        
        HashSet<Node> set = new HashSet<>();
        Node cur = o1;
        while (cur != head) {
            set.add(cur);
            cur = root.get(cur);
        }
        cur = o2;
        while (cur != head) {
            if (set.contains(cur)) {
                return cur;
            }
            cur = root.get(cur);
        }
        return head;
    }

    public static void storeRoot(Node head, HashMap<Node, Node> root) {
        if (head == null) {
            return;
        }
        root.put(head.left, head);
        root.put(head.right, head);
        
        storeRoot(head.left, root);
        storeRoot(head.right, root);
    }

2). 微软折纸面试题

	//无实体树结构的树形遍历
    public static void paperFolding(int N) {
        printPaper(1, N, true);
    }

    //i是迭代条件, N是边界, f标志左右子树
    private static void printPaper(int i, int N, boolean f) {
        if (i > N) {
            return;
        }
        printPaper(i + 1, N, true);
        String s = f == true ? "凹" : "凸";
        System.out.print(s + " ");
        printPaper(i + 1, N, false);
    }

3). 序列化与反序列化(左神代码)

	public static String serializeBT(Node head) {
        //边界信息
        if (head == null) {
            return "#_";
        }
        String res = head.value + "_";
        res += serializeBT(head.left);
        res += serializeBT(head.right);
        return res;
    }   
    //反序列化二叉树
    public static Node deserializeBT(String res) {
        LinkedList<String> strings = stringsToQueue(res);
        Node node = deserialzeProcess(strings);
        return node;
    }
    private static LinkedList<String> stringsToQueue(String s) {
        String[] strs = s.split("_");
        LinkedList<String> queue = new LinkedList<>();
        for (String s1 : strs) {
            queue.add(s1);
        }
        return queue;
    }
    private static Node deserialzeProcess(LinkedList<String> queue) {
        String value = queue.poll();
        if (value.equals("#")) {
            return null;
        }
        Node node = new Node(Integer.valueOf(value));
        
        node.left = deserialzeProcess(queue);
        node.right = deserialzeProcess(queue);
        return node;
    }
举报

相关推荐

0 条评论