时间复杂度:节点个数*每个节点处理时间
二叉树题基本可用以下两种思想递归解决:
a.遍历
递归函数无返回类型,一般结果放在全局变量中或者通过参数传入
b.分治
递归函数有返回类型,分而治之
写递归三步:
1.定义,如果用分治法,很多时候无需重新定义Helper函数
2.拆解,左右子树
3.定义返回条件,一般root==null时返回,然而有时也需处理叶子节点的情况
刷题思路:用递归解决几类经典题,用非递归方式实现preorder,inorder,postorder
TreeNode的定义:
1 /** 2 * Definition of TreeNode: 3 * public class TreeNode { 4 * public int val; 5 * public TreeNode left, right; 6 * public TreeNode(int val) { 7 * this.val = val; 8 * this.left = this.right = null; 9 * } 10 * } 11 */
97. Maximum Depth of Binary Tree
简单题
1 public int maxDepth(TreeNode root) { 2 // write your code here 3 if(root ==null){ 4 return 0; 5 } 6 int left = maxDepth(root.left); 7 int right = maxDepth(root.right); 8 9 return (left>right?left:right)+1; 10 }
480. Binary Tree Paths
1 public List<String> binaryTreePaths(TreeNode root) { 2 // write your code here 3 if(root == null){ 4 return new ArrayList<>(); 5 } 6 7 List<String> totalPath = new ArrayList<>(); 8 if(root.left==null && root.right==null){ 9 totalPath.add(root.val+""); 10 return totalPath; 11 } 12 13 List<String> leftPaths = binaryTreePaths(root.left); 14 List<String> rightPaths = binaryTreePaths(root.right); 15 16 for(String path:leftPaths){ 17 totalPath.add(root.val+"->"+path); 18 } 19 20 for(String path:rightPaths){ 21 totalPath.add(root.val + "->" +path); 22 } 23 24 return totalPath; 25 }
596. Minimum Subtree
子树:只要包含一个节点,就得包含该节点所有节点
子结构:包含一个节点,可只取左右子树其中之一,或都不取
1 public class Solution { 2 /** 3 * @param root: the root of binary tree 4 * @return: the root of the minimum subtree 5 */ 6 7 private int subTreeSum = Integer.MAX_VALUE; 8 private TreeNode subTreeRoot = null; 9 public TreeNode findSubtree(TreeNode root) { 10 // write your code here 11 Helper(root); 12 return subTreeRoot; 13 } 14 15 public int Helper(TreeNode root){ 16 if(root == null){ 17 return 0; 18 } 19 20 int sum = root.val + Helper(root.left)+Helper(root.right); 21 if(sum<subTreeSum){ 22 subTreeRoot = root; 23 subTreeSum = sum; 24 } 25 26 return sum; 27 } 28 29 }
93. Balanced Binary Tree(新定义了Helper类,二刷可复习)
平衡二叉树(java中数据结构treemap就是这种数据结构)
定义:任何一个节点,左子树和右子树深度相差不能超过1,高度logN
用递归的思想拆解即:根节点的左子树和有字数相差不超过1,且左右子树都是平衡二叉树
1 class BalancedHelper{ 2 public boolean isBalanced; 3 public int depth; 4 public BalancedHelper(boolean isBalanced,int depth){ 5 this.depth = depth; 6 this.isBalanced = isBalanced; 7 } 8 } 9 10 public class Solution { 11 /** 12 * @param root: The root of binary tree. 13 * @return: True if this Binary tree is Balanced, or false. 14 */ 15 public boolean isBalanced(TreeNode root) { 16 // write your code here 17 return Helper(root).isBalanced; 18 } 19 20 public BalancedHelper Helper(TreeNode root){ 21 if(root == null){ 22 return new BalancedHelper(true,0); 23 } 24 25 BalancedHelper leftBalance = Helper(root.left); 26 BalancedHelper rightBalance = Helper(root.right); 27 28 if(!leftBalance.isBalanced || !rightBalance.isBalanced){ 29 return new BalancedHelper(false,-1); 30 } 31 32 if(Math.abs(leftBalance.depth-rightBalance.depth)>1){ 33 return new BalancedHelper(false,-1); 34 } 35 36 return new BalancedHelper(true,1+Math.max(leftBalance.depth,rightBalance.depth)); 37 } 38 }
597. Subtree with Maximum Average
1 class AverageHelper{ 2 public int count; 3 public int sum; 4 5 public AverageHelper(int count, int sum){ 6 this.count = count; 7 this.sum = sum; 8 } 9 } 10 11 public class Solution { 12 /** 13 * @param root: the root of binary tree 14 * @return: the root of the maximum average of subtree 15 */ 16 public double maxAverage = Integer.MIN_VALUE; 17 public TreeNode maxNode = null; 18 public TreeNode findSubtree2(TreeNode root) { 19 // write your code here 20 Helper(root); 21 return maxNode; 22 } 23 24 public AverageHelper Helper(TreeNode root){ 25 if(root == null){ 26 return new AverageHelper(0,0); 27 } 28 29 AverageHelper leftAverage = Helper(root.left); 30 AverageHelper rightAverage = Helper(root.right); 31 32 double average = (root.val + leftAverage.sum + rightAverage.sum)*1.0/(1 + leftAverage.count + rightAverage.count); 33 if(average>maxAverage){ 34 maxAverage = average; 35 maxNode = root; 36 } 37 38 return new AverageHelper(1+leftAverage.count+rightAverage.count,root.val+leftAverage.sum+rightAverage.sum); 39 } 40 }
578. Lowest Common Ancestor III(必须复习重刷,逻辑有点绕,细节非常容易错)
LCA:Lowest Common Ancestor(最近公共祖先)
1.如果给定parent node,根据父指针顺序找到root的path,再倒序遍历找到第一个分叉节点,即为LCA
2.不给parent node 给定根节点(code如下)
1 class LCAHelper{ 2 public boolean isExistA; 3 public boolean isExistB; 4 public TreeNode node; 5 public LCAHelper(boolean isExistA, boolean isExistB, TreeNode node){ 6 this.isExistA = isExistA; 7 this.isExistB = isExistB; 8 this.node = node; 9 } 10 } 11 12 public class Solution { 13 /* 14 * @param root: The root of the binary tree. 15 * @param A: A TreeNode 16 * @param B: A TreeNode 17 * @return: Return the LCA of the two nodes. 18 */ 19 20 public TreeNode lowestCommonAncestor3(TreeNode root, TreeNode A, TreeNode B) { 21 // write your code here 22 LCAHelper rootHelper = Helper(root,A,B); 23 if (rootHelper.isExistA && rootHelper.isExistB){ 24 return rootHelper.node; 25 } 26 27 return null; 28 } 29 30 31 public LCAHelper Helper(TreeNode root, TreeNode A, TreeNode B){ 32 if(root == null){ 33 return new LCAHelper(false,false,null); 34 } 35 36 LCAHelper leftHelper = Helper(root.left, A, B); 37 LCAHelper rightHelper = Helper(root.right, A, B); 38 39 boolean isExistA = (root==A)||(leftHelper.isExistA)||(rightHelper.isExistA); 40 boolean isExistB = (root==B)||(leftHelper.isExistB)||(rightHelper.isExistB); 41 42 if(root ==A || root == B){ 43 return new LCAHelper(isExistA, isExistB, root); 44 } 45 46 if(leftHelper.node!=null && rightHelper.node!=null){ 47 return new LCAHelper(isExistA,isExistB,root); 48 } 49 50 if(leftHelper.node!=null){ 51 return new LCAHelper(isExistA, isExistB,leftHelper.node); 52 } 53 54 if(rightHelper.node != null){ 55 return new LCAHelper(isExistA, isExistB, rightHelper.node); 56 } 57 58 return new LCAHelper(isExistA, isExistB, null); 59 } 60 }
95. Validate Binary Search Tree
BST:Binary Search Tree (二叉查找树)
定义:左子树都比根节点小,右子树不小于根节点
BST的中序遍历是不下降序列,但反过来未必BST
1 class BSTHelper{ 2 public boolean isValidBST; 3 public int max; 4 public int min; 5 public BSTHelper(boolean isValidBST, int min, int max){ 6 this.isValidBST = isValidBST; 7 this.min = min; 8 this.max = max; 9 } 10 } 11 public class Solution { 12 /** 13 * @param root: The root of binary tree. 14 * @return: True if the binary tree is BST, or false 15 */ 16 public boolean isValidBST(TreeNode root) { 17 // write your code here 18 return Helper(root).isValidBST; 19 } 20 21 public BSTHelper Helper(TreeNode root){ 22 if(root == null){ 23 return new BSTHelper(true,Integer.MAX_VALUE, Integer.MIN_VALUE); 24 } 25 26 BSTHelper leftHelper = Helper(root.left); 27 BSTHelper rightHelper = Helper(root.right); 28 29 if(!leftHelper.isValidBST || !rightHelper.isValidBST){ 30 return new BSTHelper(false,0, 0); 31 } 32 33 if(root.left!= null && leftHelper.max >= root.val){ 34 return new BSTHelper(false,0,0); 35 } 36 37 if(root.right!=null && rightHelper.min <= root.val){ 38 return new BSTHelper(false,0,0); 39 } 40 41 return new BSTHelper(true,Math.min(leftHelper.min,root.val),Math.max(rightHelper.max, root.val)); 42 } 43 }
453. Flatten Binary Tree to Linked List
1 public void flatten(TreeNode root) { 2 // write your code here 3 Helper(root); 4 } 5 6 public TreeNode Helper(TreeNode root){ 7 if(root == null){ 8 return null; 9 } 10 11 TreeNode leftLast = Helper(root.left); 12 TreeNode rightLast = Helper(root.right); 13 14 if(leftLast!=null){ 15 leftLast.right = root.right; 16 root.right = root.left; 17 root.left = null; 18 } 19 20 if(rightLast!=null){ 21 return rightLast; 22 } 23 24 if(leftLast!=null){ 25 return leftLast; 26 } 27 28 return root; 29 }