跟着左神学算法:P6 二叉树

109 阅读1分钟

P6 二叉树

二叉树的结构

    class TreeNode {
        int val;
        TreeNode left;
        TreeNode right;

        TreeNode() {
        }

        TreeNode(int val) {
            this.val = val;
        }

        TreeNode(int val, TreeNode left, TreeNode right) {
            this.val = val;
            this.left = left;
            this.right = right;
        }
    }

二叉树的先序、中序、后序遍历

先序遍历

    // 递归
    List<Integer> res = new ArrayList<>();

    public List<Integer> preOrderTraversal(TreeNode root) {
        if (root == null) {
            return Collections.emptyList();
        }
        res.add(root.val);
        if (root.left != null) {
            preOrderTraversal(root.left);
        }
        if (root.right != null) {
            preOrderTraversal(root.right);
        }
        return res;
    }

    // 非递归
    public List<Integer> preOrderTraversal(TreeNode root) {
        if (root == null) {
            return Collections.emptyList();
        }
        Stack<TreeNode> stack = new Stack<>();
        stack.push(root);
        TreeNode node = null;
        List<Integer> res = new ArrayList<>(101);
        while (!stack.isEmpty()) {
            node = stack.pop();
            res.add(node.val);
            if (node.right != null) {
                stack.push(node.right);
            }
            if (node.left != null) {
                stack.push(node.left);
            }
        }
        return res;
    }

中序遍历

    // 递归
    List<Integer> res = new ArrayList<>();

    public List<Integer> inOrderTraversal(TreeNode root) {
        if (root == null) {
            return Collections.emptyList();
        }
        if (root.left != null) {
            inOrderTraversal(root.left);
        }
        res.add(root.val);
        if (root.right != null) {
            inOrderTraversal(root.right);
        }
        return res;
    }

    // 非递归
     public List<Integer> inOrderTraversal(TreeNode root) {
        if (root == null) {
            return Collections.emptyList();
        }
        List<Integer> res = new ArrayList<>();
        Stack<TreeNode> stack = new Stack<>();
        TreeNode node = root;
        while (!stack.isEmpty() || node != null) {
            if (node != null) {
                stack.push(node);
                node = node.left;
            } else {
                node = stack.pop();
                res.add(node.val);
                node = node.right;
            }
        }
        return res;
    }

后序遍历

    // 递归
    public List<Integer> postOrderTraversal(TreeNode root) {
        if (root == null) {
            return Collections.emptyList();
        }
        List<Integer> res = new ArrayList<>(100);
        help(root, res);
        return res;
    }

    public void help(TreeNode root, List<Integer> res) {
        if (root.left != null) {
            help(root.left, res);
        }
        if (root.right != null) {
            help(root.right, res);
        }
        res.add(root.val);
    }


    // 非递归 
    public List<Integer> postOrderTraversal(TreeNode root) {
        if (root == null) {
            return Collections.emptyList();
        }
        Stack<TreeNode> stack = new Stack<>();
        Stack<Integer> help = new Stack<>();
        stack.push(root);
        TreeNode node = null;
        List<Integer> res = new ArrayList<>(101);
        while (!stack.isEmpty()) {
            node = stack.pop();
            help.push(node.val);
            if (node.left != null) {
                stack.push(node.left);
            }
            if (node.right != null) {
                stack.push(node.right);
            }
        }
        while (!help.isEmpty()) {
            res.add(help.pop());
        }
        return res;
    }

二叉树的宽度优先遍历

    public List<Integer> levelOrderTraversal(TreeNode root) {
        if (root == null) {
            return Collections.emptyList();
        }
        Queue<TreeNode> queue = new LinkedList<>();
        List<Integer> res = new ArrayList<>();
        queue.add(root);
        TreeNode node = null;
        while (!queue.isEmpty()) {
            node = queue.poll();
            res.add(node.val);
            if (node.left != null) {
                queue.add(node.left);
            }
            if (node.right != null) {
                queue.add(node.right);
            }
        }
        return res;
    }

判断一棵二叉树是不是搜索二叉树

搜索二叉树

左子树节点都比根节点小,右子树节点都比根节点大

中序遍历判断是否是搜索二叉树

    public boolean isValidBST(TreeNode root) {
        return isValidBST(root, Long.MIN_VALUE, Long.MAX_VALUE);
    }

    public boolean isValidBST(TreeNode node, long lower, long upper) {
        if (node == null) {
            return true;
        }
        if (node.val <= lower || node.val >= upper) {
            return false;
        }
        return isValidBST(node.left, lower, node.val) && isValidBST(node.right, node.val, upper);
    }

判断一棵二叉树是不是完全二叉树

完全二叉树

满二叉树是完全二叉树,如果不是满二叉树,最后一层节点从左到右排列也是完全二叉树

宽度遍历二叉树判断是否完全二叉树

  1. 任意一个节点,如果只有右子树没有左子树,就不是完全二叉树
  2. 如果遇到一个不同时拥有两个孩子的节点,之后的节点都是叶子节点,否则就不是完全二叉树
    public boolean levelOrderTraversal(TreeNode root) {
        if (root == null) {
            return Collections.emptyList();
        }
        Queue<TreeNode> queue = new LinkedList<>();
        queue.add(root);
        TreeNode node = null;
        boolean res = true;
        boolean leaf = false;
        while (!queue.isEmpty()) {
            node = queue.poll();
            if(!leaf && node.left == null && node.right == null) {
                leaf = true;
            }
            if(leaf && (node.left != null || node.right != null)) {
                res = false;
            }
            if(node.left == null && node.right != null) {
                res = false;
            }
            if (node.left != null) {
                queue.add(node.left);
            }
            if (node.right != null) {
                queue.add(node.right);
            }
        }
        return res;
    }

判断一棵二叉树是不是满二叉树

满二叉树

每一层节点都是满的二叉树是满二叉树

最大深度和节点个数判断是不是满二叉树

节点个数是 N,深度是 h,两者满足 N=2h1N = 2^h-1 就是满二叉树

    public boolean fullTree(TreeNode root) {
        int h = dfs(root);
        int n = leafs(root);
        return n == ((2 << (h - 1)) - 1);
    }

    public int  leafs(TreeNode root) {
        if(root == null) {
            return 0;
        }
        return leafs(root.left) + leafs(root.right) + 1;
    }

    public int dfs(TreeNode root, int depth) {
        if(root == null) {
            return 0;
        }
        return Math.max(dfs(root.left), dfs(root.right)) + 1;
    }

判断一棵二叉树是不是平衡二叉树

平衡二叉树

对于每一个节点,左子树和右子树深度之差不超过1

递归求解是不是平衡二叉树

    static class ReturnType {
        int depth;
        boolean isBalanced;

        ReturnType(int depth, boolean isBalanced) {
            this.depth = depth;
            this.isBalanced = isBalanced;
        }
    }

    public boolean isBalanced(TreeNode root) {
        return isBalanced2(root).isBalanced;
    }

    public ReturnType isBalanced2(TreeNode root) {
        if (root == null) {
            return new ReturnType(0, true);
        }
        ReturnType l = isBalanced2(root.left);
        ReturnType r = isBalanced2(root.right);
        boolean isBalanced = l.isBalanced && r.isBalanced && Math.abs(l.depth - r.depth) <= 1;
        int depth = Math.max(l.depth, r.depth) + 1;
        return new ReturnType(depth, isBalanced);
    }

最低公共祖节点

给定两个二叉树节点 node1 和 node2,找到它们的最低公共祖节点

    public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
        if (root == null) {
            return null;
        } else if (root == p) {
            return p;
        } else if (root == q) {
            return q;
        }
        TreeNode lRes = lowestCommonAncestor(root.left, p, q);
        TreeNode rRes = lowestCommonAncestor(root.right, p, q);
        if (lRes != null && rRes != null) {
            return root;
        } else if (lRes == null && rRes == null) {
            return null;
        } else if (lRes != null) {
            return lRes;
        } else {
            return rRes;
        }
    }

在二叉树中找到一个节点的后继节点

后继节点:中序遍历之后节点后面的那个节点
前驱节点:中序遍历之后节点前面的那个节点

    public TreeNode nextNode(TreeNode root, TreeNode node) {
        TreeNode nextNode = null;
        Stack<TreeNode> stack = new Stack<>();
        TreeNode p = root;
        while(p != null || !stack.isEmpty()) {
            if(p ! = null) {
                stack.push(p);
                p = p.left;
            } else{
                p = stack.pop();
                if(p == node) {
                    if(!stack.isEmpty()) {
                        nextNode = stack.pop();
                    } else {
                        nextNode = node.right;
                    }
                    break;
                }
            }
        }
        return nextNode;
    }

二叉树的序列化和反序列化

    // Encodes a tree to a single string.
    public String serialize(TreeNode root) {
        return serialize(root, new StringBuffer("")).toString();
    }

    public StringBuffer serialize(TreeNode root, StringBuffer sb) {
        if (root == null) {
            sb.append("#,");
        } else {
            sb.append(String.valueOf(root.val)).append(",");
            sb = serialize(root.left, sb);
            sb = serialize(root.right, sb);
        }
        return sb;
    }

    // Decodes your encoded data to tree.
    public TreeNode deserialize(String data) {
        List<String> list = new LinkedList<>(Arrays.asList(data.split(",")));
        return deserialize(list);
    }

    public TreeNode deserialize(List<String> list) {
        if (list.get(0).equals("#")) {
            list.remove(0);
            return null;
        }
        TreeNode root = new TreeNode(Integer.parseInt(list.get(0)));
        list.remove(0);
        root.left = deserialize(list);
        root.right = deserialize(list);
        return root;
    }

判断一棵二叉树是不是另一棵二叉树的子树

 private boolean isSame(TreeNode t1, TreeNode t2) {
        if (t1 == null && t2 == null) {
            return true;
        }

        if (t1 == null || t2 == null) {
            return false;
        }

        return t1.val == t2.val && isSame(t1.left, t2.left) && isSame(t1.right, t2.right);
    }

    public boolean checkSubTree(TreeNode t1, TreeNode t2) {
        if (t1 == null) {
            return t2 == null;
        }

        return isSame(t1, t2) || checkSubTree(t1.left, t2) || checkSubTree(t1.right, t2);
    }