算法:二叉树
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 }
解法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; } }
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 }
解法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; } }
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; } }
解法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; } }
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 }
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; }
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; } }
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; } }
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 }
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); } }
解法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; } }
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; } }
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; } }
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; } }
解法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; } }
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; } }
解法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; } }
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); } }
解法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; } }
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; } } }
解法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; } } }
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; } }
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); } }
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); } }
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; } }
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; } }