算法:二叉树


1. Maximum Depth of Binary Tree: https://leetcode.com/problems/maximum-depth-of-binary-tree/

最大深度:

解法1:<Recursive>

1 public class Solution {
2     public int maxDepth(TreeNode root) {
3         if (root == null) return 0;
4         int rst = Math.max(maxDepth(root.left), maxDepth(root.right));
5         return rst + 1;
6     }
7 }
View Code

解法2:<Iterative>(层序遍历思想: queue+size+cnt;)

public class Solution {
    public int maxDepth(TreeNode root) {
        //Iterative--层序遍历思想
        if (root == null) return 0;
        Queue<TreeNode> queue = new LinkedList<>();
        queue.offer(root);
        int cnt = 0;
        while (!queue.isEmpty()) {
            int size = queue.size();
            for (int i = 0; i < size; i++) {
                TreeNode cur = queue.poll();
                if (cur.left != null) queue.offer(cur.left);
                if (cur.right != null) queue.offer(cur.right);
            }
            cnt++;
        }
        return cnt;
    }
}
View Code

 

2. Minimum Depth of Binary Tree:https://leetcode.com/problems/minimum-depth-of-binary-tree/

最小深度:

解法1:<Recursice>(左节点为null返回右边的min+1;右节点为null返回左边的min+1;都不为null则返回Math.min()+1;)

1 public class Solution {
2     public int minDepth(TreeNode root) {
3         if (root == null) return 0;
4         if (root.left == null) return minDepth(root.right) + 1;
5         if (root.right == null) return minDepth(root.left) + 1;
6         int rst = Math.min(minDepth(root.left), minDepth(root.right));
7         return rst + 1;
8     }
9 }
View Code

解法2:<Iterative>(层序遍历思想;找到第一个叶节点就返回。max的初始cnt是零,因为它是最后循环结束后return的。而min初始cnt是1,因为它是在循环内部return的,最后的cnt改为cnt+1+2等等都不会错。)

public class Solution {
    public int minDepth(TreeNode root) {
        if (root == null) return 0;
        Queue<TreeNode> queue = new LinkedList<>();
        queue.offer(root);
        int count = 1;
        while (!queue.isEmpty()) {
            int size = queue.size();
            for (int i = 0; i < size; i++) {
                TreeNode node = queue.poll();
                if (node.left == null && node.right == null) return count;
                if (node.left != null) queue.offer(node.left);
                if (node.right != null) queue.offer(node.right);
            }
            count++;
        }
        return count;
    }
}
View Code

3. Binary Tree Inorder Traversal:https://leetcode.com/problems/binary-tree-inorder-traversal/

中序遍历:

解法1:<Recursive>(addAll)

public class Solution {
    public List<Integer> inorderTraversal(TreeNode root) {
        List<Integer> rst = new ArrayList<>();
        if (root == null) return rst;
        rst.addAll(inorderTraversal(root.left));
        rst.add(root.val);
        rst.addAll(inorderTraversal(root.right));
        return rst;
    }
}
View Code

解法2:<Iterative>(1.外循环while(||);2.内循环-入栈,左移;3.出栈,添值,右移)(中序遍历循环两个判断条件是因为 root不是提前push的,而前序遍历是提前push进root的)

public class Solution {
    public List<Integer> inorderTraversal(TreeNode root) {
        List<Integer> rst = new ArrayList<Integer>();
        Stack<TreeNode> stack = new Stack<TreeNode>();
        TreeNode cur = root;
        while (cur != null || !stack.empty()) {
            while (cur != null) {
                stack.push(cur);
                cur = cur.left;
            }
            cur = stack.pop();
            rst.add(cur.val);
            cur = cur.right;
        }
        return rst;
    }
}
View Code

4. Binary Tree Preorder Traversal: https://leetcode.com/problems/binary-tree-preorder-traversal/

前序遍历:(放入root; while(!empty), 出栈,添值,右左入栈)

解法:<Iterative>

 1 public class Solution {
 2     public List<Integer> preorderTraversal(TreeNode root) {
 3         List<Integer> rst = new ArrayList<>();
 4         Stack<TreeNode> stack = new Stack<>();
 5         if (root == null) return rst;
 6         stack.push(root);
 7         while (!stack.empty()) {
 8             TreeNode cur = stack.pop();
 9             rst.add(cur.val);
10             if (cur.right != null) stack.push(cur.right);
11             if (cur.left != null) stack.push(cur.left);
12         }
13         return rst;
14     }
15 }
View Code

5. Binary Tree Postorder Traversal: https://leetcode.com/problems/binary-tree-postorder-traversal/

后序遍历:(pre-NLR, post-LRN, ArrayList.add(0,val)直接得到LRN;  和前序遍历区别:list;左右入栈)

解法:<Iterative>

public List<Integer> postorderTraversal(TreeNode root) {
    List<Integer> list = new ArrayList<>();
    if(root == null) return list;
    Stack<TreeNode> stack = new Stack<>();
    stack.push(root);
    while(!stack.empty()){
        root = stack.pop();
        list.add(0, root.val);
        if(root.left != null) stack.push(root.left);
        if(root.right != null) stack.push(root.right);
    }
    return list;
}
View Code

6. Binary Tree Level Order Traversal: https://leetcode.com/problems/binary-tree-level-order-traversal/

层序遍历:(queue+size/list+add/左右入列)

解法:<Iterative>

public class Solution {
    public List<List<Integer>> levelOrder(TreeNode root) {
        Queue<TreeNode> queue = new LinkedList<>();
        List<List<Integer>> rst = new ArrayList<>();
        if (root == null) return rst;
        queue.offer(root);
        while (!queue.isEmpty()) {
            List<Integer> list = new ArrayList<>();
            int size = queue.size();
            for (int i = 0; i < size; i++){
                TreeNode node = queue.poll();
                list.add(node.val);
                if (node.left != null) queue.offer(node.left);
                if (node.right != null) queue.offer(node.right);
            }
            rst.add(list);
        }
        return rst;
    }
}
View Code

7. Binary Tree Level Order Traversal II:https://leetcode.com/problems/binary-tree-level-order-traversal-ii/

层序遍历II-页到根顺序:

解法:(与Level Order Traverse 方法相同。队列。利用LinkedList的addFirst方法。ps:rst为List<List<>>时不存在addFirst方法, 必须是LinkdeList<List<>>。也可以用ArrayList和LinkedList的add(index, E)的方法)

public class Solution {
    public List<List<Integer>> levelOrderBottom(TreeNode root) {
        Queue<TreeNode> queue = new LinkedList<>();
        LinkedList<List<Integer>> rst = new LinkedList<>();
        if (root == null) return rst;
        queue.offer(root);
        while (!queue.isEmpty()) {
            int size = queue.size();
            List<Integer> list = new LinkedList<>();
            for (int i = 0; i < size; i++) {
                TreeNode node = queue.poll();
                list.add(node.val);
                if (node.left != null) queue.offer(node.left);
                if (node.right != null) queue.offer(node.right);
            }
            rst.addFirst(list);
        }
        return rst;
    }
}
View Code

8. Binary Tree Zigzag Level Order Traversal: https://leetcode.com/problems/binary-tree-zigzag-level-order-traversal/

曲折层序遍历(每层依次左右、右左、左右……):

解法:<BFS>(和层序遍历方法相同。增加order作为boolean判断来选择list.add和list.add(0,val))

 1 public class Solution {
 2     public List<List<Integer>> zigzagLevelOrder(TreeNode root) {
 3         List<List<Integer>> rst = new LinkedList<>();
 4         Queue<TreeNode> queue = new LinkedList<>();
 5         if (root == null) return rst;
 6         queue.offer(root);
 7         boolean order = true;
 8         while (!queue.isEmpty()) {
 9             int size = queue.size();
10             List<Integer> list = new LinkedList<>();
11             for (int i = 0; i < size; i++) {
12                 TreeNode node = queue.poll();
13                 if (order) {
14                     list.add(node.val);
15                 } else {
16                     list.add(0, node.val);
17                 }
18                 if (node.left != null) queue.offer(node.left);
19                 if (node.right != null) queue.offer(node.right);
20             }
21             order = !order;
22             rst.add(list);
23         }
24         return rst;
25     }
26 }
View Code

9. Symmetric Tree: https://leetcode.com/problems/symmetric-tree/

对称树:

解法1:<Recursive>(左节点和右节点的比较,所以需要helper函数,判断left和right的null与val;递归左左和右右,左右和右左)

public class Solution {
    public boolean isSymmetric(TreeNode root) {
        if (root == null) return true;
        return helper(root.left, root.right);
    }
    public boolean helper(TreeNode left, TreeNode right) {
        if (left == null || right == null) return left == right;
        if (left.val != right.val) return false;
        return helper(left.left, right.right) && helper(left.right, right.left);
    }
}
View Code

解法2:<Iterative>(Stack, 每次pop两个对称的节点,判断两个节点是否满足条件。再push进四个节点)

public class Solution {
    public boolean isSymmetric(TreeNode root) {
        if (root == null) return true;
        Stack<TreeNode> stack = new Stack<>();
        stack.push(root.left);
        stack.push(root.right);
        while (!stack.empty()) {
            TreeNode n1 = stack.pop(), n2 = stack.pop();
            if (n1 == null && n2 == null) continue;
            if (n1 == null || n2 == null || n1.val != n2.val) return false;
            stack.push(n1.right);
            stack.push(n2.left);
            stack.push(n1.left);
            stack.push(n2.right);
        }
        return true;
    }
}
View Code

10. Same Tree: https://leetcode.com/problems/same-tree/

判断两树是否相同:

Recursive解法:(判断null,判断值,迭代)

public class Solution {
    public boolean isSameTree(TreeNode p, TreeNode q) {
        if (p == null && q == null) return true;
        if (p != null && q !=null && p.val == q.val)
            return isSameTree(p.left, q.left) && isSameTree(p.right, q.right);
        return false;
    }
}
View Code

Iterative解法:(首先判断head; 每次push左右节点,并且push一个节点都要比较size-有null不同则返回false;每次pop一个节点比较值是否相等;)

public class Solution {
    public boolean isSameTree(TreeNode p, TreeNode q) {
        if (p == null && q == null) return true;
        if (p == null || q == null || p.val != q.val) return false;
        Stack<TreeNode> stack1 = new Stack<>();
        Stack<TreeNode> stack2 = new Stack<>();
        stack1.push(p);
        stack2.push(q);
        while (!stack1.empty()){
            TreeNode cur1 = stack1.pop();
            TreeNode cur2 = stack2.pop();
            if (cur1.val != cur2.val) return false;
            if (cur1.left != null) stack1.push(cur1.left);
            if (cur2.left != null) stack2.push(cur2.left);
            if (stack1.size() != stack2.size()) return false;
            if (cur1.right != null) stack1.push(cur1.right);
            if (cur2.right != null) stack2.push(cur2.right);
            if (stack1.size() != stack2.size()) return false;
        }
        return true;
    }
}
View Code

11. Invert Binary Tree: https://leetcode.com/problems/invert-binary-tree/

反转二叉树:

解法1:(Recursive)

public class Solution {
    public TreeNode invertTree(TreeNode root) {
        if (root == null) return root;
        TreeNode tmp = invertTree(root.right);
        root.right = invertTree(root.left);
        root.left = tmp;
        return root;
    }
}
View Code

解法2:(Iterative 层序遍历思想 queue+swap+offer)

public class Solution {
    public TreeNode invertTree(TreeNode root) {
        if (root == null) return null;
        Queue<TreeNode> queue = new LinkedList<>();
        queue.offer(root);
        while (!queue.isEmpty()) {
            TreeNode node = queue.poll();
            //swap;
            TreeNode tmp = node.right;
            node.right = node.left;
            node.left = tmp;
            //offer;
            if (node.left != null) queue.offer(node.left);
            if (node.right != null) queue.offer(node.right);
        }
        return root;
    }
}
View Code

12. Balanced Binary Tree:https://leetcode.com/problems/balanced-binary-tree/

平衡二叉树(两个子树的深度差不超过1):

解法1:(利用方法depth,要求两个子树深度差小于1且两个子树均为平衡树)

(1.if,rst,return 1&& ;  2.depth(),if-0,rst,return rst+1)

public class Solution {
    public boolean isBalanced(TreeNode root) {
        if (root == null) return true;
        int rst = Math.abs(depth(root.left) - depth(root.right));
        return (rst <= 1) && isBalanced(root.left) && isBalanced(root.right);
    }
    public int depth(TreeNode root) {
        if (root == null) return 0;
        int rst = Math.max(depth(root.left), depth(root.right));
        return rst + 1;
    }
}
View Code

解法2:(只遍历一次 用-1记录不平衡的子树;相当于自底向上遍历。解法1中首先root求左右深度O(N), 然后每个节点都要求左右深度, 所以是O(NlogN)? 而解法2每次返回节点的高度或者-1 最后判断值是否是-1即可,O(N))

(1.return !=-1;  2.height: lh-if,rh-if; if(>1); return max()+1;)

public class Solution {
    public boolean isBalanced(TreeNode root) {
        return height(root) != -1;
    }
    public int height(TreeNode root) {
        if (root == null) return 0;
        int lh = height(root.left);
        if (lh == -1) return -1;
        int rh = height(root.right);
        if (rh == -1) return -1;
        if (Math.abs(lh - rh) > 1) return -1;
        return Math.max(lh, rh) + 1;
    }
}
View Code

13. Validate Binary Search Tree: https://leetcode.com/problems/validate-binary-search-tree/

验证二叉搜索树:

解法1:(递归;helper(root, lo, hi);判断每一节点是否在其所属范围之内)

public class Solution {
    public boolean isValidBST(TreeNode root) {
        return helper(root, Long.MIN_VALUE, Long.MAX_VALUE);
    }
    public boolean helper(TreeNode root, long lo, long hi) {
        if (root == null) return true;
        if (root.val >= hi || root.val <= lo) return false;
        return helper(root.left, lo, root.val) && helper(root.right, root.val, hi);
    }
}
View Code

解法2:(迭代;中序遍历思想-中序遍历出来的数即为升序;pre记录前一节点;)

public class Solution {
    public boolean isValidBST(TreeNode root) {
        Stack<TreeNode> stack = new Stack<>();
        TreeNode cur = root;
        TreeNode pre = null;
        while (cur != null || !stack.empty()) {
            while (cur != null) {
                stack.push(cur);
                cur = cur.left;
            }
            cur = stack.pop();
            if (pre != null && pre.val >= cur.val) return false;
            pre = cur;
            cur = cur.right;
        }
        return true;
    }
}
View Code

14. Lowest Common Ancestor of a Binary Search Tree: https://leetcode.com/problems/lowest-common-ancestor-of-a-binary-search-tree/

BST-最低公共祖先:

解法1:(递归)(利用BST的特性,比两个都大则递归左边,比两个都小则递归右边)

public class Solution {
    public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
        if(root.val > p.val && root.val > q.val){
            return lowestCommonAncestor(root.left, p, q);
        }else if(root.val < p.val && root.val < q.val){
            return lowestCommonAncestor(root.right, p, q);
        }else{
            return root;
        }
    }
}
View Code

解法2:(迭代)(与递归类似,while(true)里迭代)

public class Solution {
    public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
        while (true) {
            if (root.val > p.val && root.val > q.val)
                root = root.left;
            else if (root.val < p.val && root.val < q.val)
                root = root.right;
            else
                return root;
        }
    }
}
View Code

15. Lowest Common Ancestor of a Binary Tree:https://leetcode.com/problems/lowest-common-ancestor-of-a-binary-tree/

最低公共祖先:

解法:(递归 root为最低祖先条件是A和B分别在左右子树; )

(如果找到了就返回LCA;如果只找到A就返回A;只找到B就返回B;左右不为空返回root;左空返回右,右空返回左)

(具体:1.null/A/B 返回root;2.递归得left/right;3.左右非空返回root,有空的则返回非空)

public class Solution {
    // 在root为根的二叉树中找A,B的LCA:
    // 如果找到了就返回这个LCA
    // 如果只碰到A,就返回A
    // 如果只碰到B,就返回B
    // 如果都没有,就返回null
    public TreeNode lowestCommonAncestor(TreeNode root, TreeNode node1, TreeNode node2) {
        if (root == null || root == node1 || root == node2) {
            return root;
        }
        
        // Divide
        TreeNode left = lowestCommonAncestor(root.left, node1, node2);
        TreeNode right = lowestCommonAncestor(root.right, node1, node2);
        
        // Conquer
        if (left != null && right != null) {
            return root;
        } 
        if (left != null) {
            return left;
        }
        if (right != null) {
            return right;
        }
        return null;
    }
}
View Code

16. Path Sum: https://leetcode.com/problems/path-sum/

判断是否存在根到叶路径经过的值的和等于给定值:

解法:<Recursive>

public class Solution {
    public boolean hasPathSum(TreeNode root, int sum) {
        if (root == null) return false;
        if (root.left == null && root.right == null) return root.val == sum;
        return hasPathSum(root.left, sum - root.val) || hasPathSum(root.right, sum - root.val);
    }
}
View Code

17. Path Sum II:https://leetcode.com/problems/path-sum-ii/

返回路径值:

解法:<Recursion>(和数组里子集的题类似。每次add进当前值,递归left和right,再remove即返回上一节点。终止条件是叶节点--及左右子节点都为null,如果=val了,那么add,remove,return;否则return;)

public class Solution {
    public List<List<Integer>> pathSum(TreeNode root, int sum) {
        List<List<Integer>> rst = new ArrayList<>();
        List<Integer> list = new ArrayList<>();
        helper(root, sum, list, rst);
        return rst;
    }
    public void helper(TreeNode root, int sum, List<Integer> list, List<List<Integer>> rst) {
        if (root == null) return;
        if (root.left == null && root.right == null) {
            if (root.val == sum) {
                list.add(root.val);
                rst.add(new ArrayList<Integer>(list));
                list.remove(list.size() - 1);
            }
            return;
        }
        list.add(root.val);
        helper(root.left, sum - root.val, list, rst);
        helper(root.right, sum - root.val, list, rst);
        list.remove(list.size() - 1);
    }
}
View Code

18.Construct Binary Tree from Preorder and Inorder Traversal: http://www.lintcode.com/en/problem/construct-binary-tree-from-preorder-and-inorder-traversal/

根据前序遍历和中序遍历构造树:

(TreeNode helper(in,pre,inS,inE,preS); 如果(pre>len||inS>inE)null; 找出in中位置;递归得出left,right)

public class Solution {
    /**
     *@param preorder : A list of integers that preorder traversal of a tree
     *@param inorder : A list of integers that inorder traversal of a tree
     *@return : Root of a tree
     */
    public TreeNode buildTree(int[] preorder, int[] inorder) {
        // write your code here
        return helper(preorder, inorder, 0, 0, inorder.length - 1);
    }
    public TreeNode helper(int[] pre, int[] in, int preStart, int inStart, int inEnd) {
        if (preStart > pre.length || inStart > inEnd) return null;
        TreeNode root = new TreeNode(pre[preStart]);
        int index = 0;
        for (int i = inStart; i <= inEnd; i++) {
            if (in[i] == pre[preStart]) {
                index = i;
                break;
            }
        }
        root.left = helper(pre, in, preStart + 1, inStart, index - 1);
        root.right = helper(pre, in, preStart + index- inStart + 1, index + 1, inEnd);
        return root;
    }
}
View Code

19. Construct Binary Tree from Inorder and Postorder Traversal: https://leetcode.com/problems/construct-binary-tree-from-inorder-and-postorder-traversal/

根据中序遍历和后序遍历构造树:

(helper(in,post,inS,inE,postE); 如果(preE<0||inS>inE)null; 找出in中位置;递归;)

public class Solution {
    public TreeNode buildTree(int[] inorder, int[] postorder) {
        return helper(inorder, postorder, postorder.length - 1, 0, inorder.length - 1);
    }
    public TreeNode helper(int[] in, int[] post, int postEnd, int inStart, int inEnd) {
        if (postEnd < 0 || inStart > inEnd) return null;
        TreeNode root = new TreeNode(post[postEnd]);
        int index = 0;
        for (int i = inStart; i <= inEnd; i++) {
            if (in[i] == post[postEnd]) {
                index = i;
                break;
            }
        }
        root.left = helper(in, post, postEnd - inEnd + index - 1, inStart, index - 1);
        root.right = helper(in, post, postEnd - 1, index + 1, inEnd);
        return root;
    }
}
View Code

原文地址:https://www.cnblogs.com/buwenyuwu/p/6587887.html