- 重建树
- 遍历树
========================================================
1.Binary Tree Level Order Traversal II(107. leetcode)横向记录树
-.这道题的DFS 解法
-思路:每层建立一个list,把node 插入到相应的每一层
-细节:1.需要一个数记录当前level, 遇到新的 level 要创建新的 list, 并且这里创建的新的list 一定在 res 的第一个, 因为level 越下面,就越靠近底层,在 res 中越前面。
-.考虑顺序:
1.考虑node 是null的情况,就返回.
2.考虑 不是叶子的情况, 查看这个 node 的level, 如果比当前的 level 要大,就要新建一个list,并且是放在最前面,因为这个是树的越底层,在返回结果越前面。
3.如果当前node 在已经遍历过的level 上,就继续 “缩小问题”,到下一层他的left 和 right node。
4.当当前 node就是叶子,就要把当前node,加入结果res,根据当前level,也是 res.size() - level - 1
public List> levelOrderBottom(TreeNode root) {
List> res = new ArrayList<>();
DFS( res, root,0);
return res;
}
public void BFS(List> res, TreeNode root, int level){
if( root == null) return;
if( level >= res.size() )
res.add(0, new ArrayList<>());
DFS(res, root.left, level + 1);
DFS(res, root.right, level + 1);
/*还原现场*/
res.get(res.size() - level -1 ).add(root.val);
}
-.-.这道题的BFS 解法
这一题和 我位运算 总结第19 题 一样 Letter Case Permutation (784.leetcode)
-. 这里需要建立一个Queue, 最好用linklist 实现,因为需要不断插入删除旧的元素,改变queue的结构, linkedlist 会更加高效
public List> levelOrderBottom(TreeNode root) {
Queue queue = new LinkedList<>();
List> res = new LinkedList<>();
if( root == null) return res;
queue.offer(root);
while( !queue.isEmpty() ) {
int size = queue.size();
List tmp = new ArrayList<>();
for(int i=0; i< size; i++) {
if(queue.peek().left != null) queue.offer(queue.peek().left);
if(queue.peek().right != null) queue.offer(queue.peek().right);
tmp.add(queue.poll().val);
}
res.add(0, tmp);
}
return res;
}
2.Average of Levels in Binary Tree(637. leetcode)
-.用 BFS 横向记录每level 的 average, 需要使用到 queue 的数据结构
public List averageOfLevels(TreeNode root) {
Queue queue = new LinkedList<>();
List< Double > res = new ArrayList<>();
queue.offer(root);
while( !queue.isEmpty() ) {
int size = queue.size();
Double sum = 0.0;
for(int i=0; i
3.Binary Tree Level Order Traversal (102.leetcode)
- 第三题 和 第一题的区别是,在res 里的顺序, 所以也就是 加入结果的时候 是插在res 的头部, 还是尾部
public List> levelOrder(TreeNode root) {
List> res = new ArrayList<>();
DFS(res; root, 0);
return res;
}
public void DFS(List> res, TreeNode root, int level) {
if( root == null ) return ;
if(level >= res.size())
res.add(new ArrayList<>());
DFS(res, root.left, level + 1);
DFS(res, root.right, level + 1);
res.get(level).add(root.val);
}
4.Minimum Depth of Binary Tree( 111 .leetcode)
-. 注意这题的的边界条件,[1,2], 所以当有一个的左子树为null 时,一定要取 left + right +1
-. 这里用 left 和 right 的原因是因为 当前的node 有 2种情况, 一种是 同时有 left 和 right child 这样子 就取Math.min() + 1, 第二种是, 只有左孩子,或者右孩子,那么就只能取 left + right + 1 因为只有一个选择。
public int minDepth(TreeNode root) {
if( root == null) return 0;
int left = minDepth(root.left);
int right = minDepth(root.rigth);
return (left =0 || right == 0) ? left+rigth+1 : Math.min(left, right) + 1;
}
5.Maximum Depth of Binary Tree(104. leetcode)
-. 这里就不需要 left 和 right, 因为只要下去一层就必须要+1, 因为不需要分情况讨论, 所以对待每个node 都是一样的操作, 不论是有2个孩子,还是只有一个孩子,或没有孩子, 都是Math.max() 操作,不需要向上面一题一样判断 是否在有个孩子为null
public int maxDepth(TreeNode root) {
if( root == null) return 0;
return Math.max(maxDepth(root.left) , maxDepth(root.right) )+1;
}
6.Balanced Binary Tree(110. leetcode) !!
-总结:
public boolean isBalanced(TreeNode root) {
return DFS(root) != -1;
}
public int DFS(TreeNode root) {
if(root == null) return 0;
int leftH = DFS(root.left);
if(leftH == -1) return -1; /* 有了左子树的返回值*/
int rightH = DFS(root.right);
if(rightH == -1) return -1; /* 有了右子树的返回值*/
if( Math.abs(leftH, rightH) >1 ) return -1; /* 同时有了左边和右边的子树*/
return Math.abs(leftH, rightH) + 1;/* 继续还原现场*/
}
7.the Same Tree(100. leetcode)
public boolean isSameTree(TreeNode p, TreeNode q) {
if(p == null && q == null)
return true;
if ((p == nul && q != null) || (p != null && q == null))
return false;
return ( p.val == q.val ) && isSameTree( p.left, q.right) && isSameTree(p.right, q.right);
}
8. Maximum Depth of N-ary Tree(559. leetcode)
- 这道题使用了 递归+loop 的解法
-注意点:
1.想要遍历到下一层(缩小问题)就调用自己
2.max 在 loop 中要保留, 但是在每层的开始要定义为0, 因为max 会作为返回值返回到上一层
public int maxDepth(Node root) {
if (root == null) return 0;
int max = 0;
for(Node node : root.children) {
int value = maxDepth( node );
max = max> value?max: value;
}
return max +1;
}
9. Path Sum(112. leetcode)
-思路:如果 node 已经reach 到 null 了,说明这条path,不满足sum == 0. 且要确保根据题意找到 整条path 的和 是Sum ,而不是半条path 的和 是sum。
public boolean hasPathSum(TreeNode root, int sum) {
if(root == null ) return false;
if( root.left == null && root.right == null && sum == 0) return true;
return hasPathSame(root.left, sum - root.val) || hasPathSum(root.right, sum - root.val);
}
10. Path Sum II (113. leetcode)
这道题用到了backtracking
public List> pathSum(TreeNode root, int sum) {
List> res = new ArrayList<>();
backtracking(TreeNode root, int sum,res, new ArrayList<>());
return res;
}
public void backtracking(TreeNode root, int sum, List> res, List tmp) {
if(root == null) return ;
tmp.add(root);
if( sum == root.val && root.left == null && root.right == null)
res.add(new ArrayList(tmp));
backtracking(root.left, sum - root.val, res, tmp);
backtracking(root.right, sum - root.val, res, tmp);
tmp.remove(tmp.size() - 1);
}
11. Path Sum III (437. leetcode)
- 本题难点:root 不是固定的
- 方法一: 缺点时间复杂度较高O(N^2)
1. root 不断更新 ->(解决方式) 2 个递归 , 一个递归root, 另一个递归子树
2. 注意第一个放法的return 里 sum 是不变化的。
public int pathSum(TreeNode root, int sum) {
if(root == null) return 0;
return findPath(root, sum) + findPath(root.left, sum)+ findPath( root.right, sum);
}
public int findPath(TreeNode root, int sum) {
if( root == null) return 0;
return (sum == root.val ? 1 : 0) + findPath(root.left, sum-root.val ) + findPath(root.right, sum - root.val);
}
方法二:!! HashMap + 递归遍历 时间复杂度 O(N)
** 对于curSum, oldSum, sum 要有能力联想到HashMap**
优化方式:1. 用空间换时间, 在方一的基础上改变, 记录 curSum - target = oldSum, 中的OldSum。免去了重新遍历改变root 时,对于整棵树的遍历。
public int pathSum(TreeNode root, int sum) {
if( root == null) return 0;
Map map = new HashMap();
return verify(root, sum, map, cur);
}
public int verify(TreeNode root, int sum, Map map , int cur) {
if( root == null ) return 0;
cur += val.root;
int totalPath = map.getOrDefault(cur - sum , 0); /* 寻找oldsum, 删掉root, 处理上一层*/
if(sum == cur) totalPath++; /* 增加current node , 处理 这一层*/
map.put(cur, map.getOrDefault(cur, 0) + 1); /* 记录现在的sum 准备进入 下一层*/
total += verify( root.left, sum, map , cur); /* 进入下一层*/
total += verify(root.right, sum, map, cur);
map.put( cur, map.get(cur) - 1); /* 还原现场, 准备回到原来那一层*/
return totalPath;
}
12. Path Sum IV (666. leetcode)
-这道题的的注意点, parent node 和 children node 在tree 里的关系, 是left child: parent 的位置 2 -1 (这里parent 的位置是从 1开始的 而不是从0 开始) right child: parent 的位置是 2 ;
- 这里要设置一个 current sum, 留到每一层, 可以通过参数的形式,也可以通过在 全局变量的形式
-.解决思路:
int sum =0;
Map map = new HashMap<>();
public int pathSum(int[] nums) {
if(nums == null || nums.length ==0) return 0;
/* 把每个element 放进 hashmap*/
for(int num : nums) {
int key = num /10;
int val = num % 10;
map.put(key, val) ;
}
DFS(nums[0], 0);
return sum;
}
public void DFS(int root , int preSum) {
int level = root/10;
int order = root % 10;
int left = (level +1)*10 + (order *2-1);
int right = (level +1)*10 + (order*2);
int curSum = preSum + map.get(level);
if( !map.containsKey(left) && !map.containsKey(right)) {
sum += curSum;
return;
}
if( map.containsKey(left)) DFS(left, curSum);
if(map.containsKey(right)) DFS(right, curSum);
}
13. Binary Tree Maximum Path Sum (124.leetcode) -> Hard level
-. 理解题意,这里是指找1 条最大路劲和,所以中间不能出现多条path
-.link: http://www.cnblogs.com/grandyang/p/4280120.html
-问题难点:
1.这道题不是 left child 和 right child比较,而是筛选root, 以及筛选
- 左子树 或 右子树 的total sum 能通过 maxValue 记录, 然后再和 上一个level 比较
- 以及当从current path 切换到 上一个level 的时候, 只能从左右path 中选择一条返回
int maxValue ;
public int maxPathSum(TreeNode root) {
maxValue = Integer.MIN_VALUE;
return maxPathDown(root);
}
public int maxPathDown(TreeNode root) {
if(root == null ) return 0;
int left = Math.max(0, maxPathDown(root.left));
int right = Math.max(0, maxPathDown(root.right));
maxValue = Math.maxValue( maxValue, left + right + root.node);
return Math.max(left, right)+ root.node;
}
14. Longest Univalue Path (687.leetcode)
1.返回值要是什么? 必须要返回 下一层的node, 才能知道parent 是不是和child 一样 -> 有root.left , root.right 所以应该返回 左边或右边的longest path
- 需要一个参数记录 longestLength -> longestLength
- 还需要一个参数记录current length -> resl 记录left's length , resR 记录 resR's length
- 从上向下遍历, 从下向上(从下至上缩小选择范围)
没有注意的点:
- 如果因为有 longestLength 记录最长的path,所以 resL, resR, 就用来记录当前的path 不用是最长的, 只是记录当前状态
2.比较的时候,不要忘记有 left + right +node.val 的可能性 - path 的话永远在纠结,是向上走 还是向下走, 所以要先记录 向下走也就是 maxValue = Math.max(maxValue, resL + resR) -> 向下走的情况 ; 但是 还要继续查看向上走的可能性 也就是通过 return, return Math.max(resL, resR);
int maxValue ;
public int longestUnivaluePath(TreeNode root) {
if( root == null) return 0;
maxValue = 0;
DFS(root);
return maxValue;
}
public int DFS(TreeNode root) {
int left = root.left != null ? DFS(root.left) : 0;
int right = root.right != null ? DFS(root.right) : 0;
int resL = root.left != null && root.left.val == root.val ? left + 1: 0;
int resR = root.right != null && root.right.val == root.val ? right+1: 0;
maxValue = Math.max( maxValue, resL + resR);
return Math.max(resL, resR);
}
15. Binary Tree Paths (257.leetcode) easy level
public List binaryTreePaths(TreeNode root) {
List result = new ArrayList<>();
if(root != null) {
if( root.left != null || root.right != null) {
helper(root.left, result, " "+ root.val);
helper(root.right, result, " " +root.val);
}
else{
result.add(root.val);
}
return result
}
}
public void helper(TreeNode root, List res, String path) {
if( root != null) {
String curStr = path +" ->" + root.val;
if(root.left != null )
helper( root.left, res, curStr);
if(root.right != null)
helper(root.right, res, curStr);
if(root.left == null && root.right == null)
res.add(curStr);
}
}
16. Subtree of Another Tree(572. leetcode)
- 注意return 是 ||, 还是 &&
- 寻找的换 ||
- 检查树是否一样的话, 用&&
解题思路: 先遍历s 中的每一个node, 然后再判断 t 是否是 S 的sbutree
public boolean isSubtree(TreeNode s, TreeNode t) {
if( s== null) return false;
if( isSame(s, t)) return true;
return isSubtree(s.left, t) || isSubtree(s.right, t);
}
public boolean isSame(TreeNode s, TreeNode t) {
if( s== nul && t == null) return true;
if( s == null || t== null) return false;
if(s.val != t.val) return false;
return isSame(s.left, t,left) && isSame( s.right, t.right);
}
17. Count Univalue Subtrees(250. leetcode)
解题思路:
- 当左边和右边孩子的值,都等于parent 的时候, count ++; 其余时候都不count++
- 当任意一边子树是null 时,是比较parent 与剩余一边的孩子的值, 相同则count++
- 当个两个 children 都是 null 时, 则count ++;
public int countUnivalSubtrees(TreeNode root) {
int [] count = new int [1];
helper(root, count);
return count[0];
}
public boolean helper(TreeNode root, int[] count){
if(root == null ) return true;
boolean left = helper( root.left, count);
boolean right = helper(root.right, count);
if(left && right ) {
if( root.left != null && root.val != root.left.val)
return false;
if( root.right != null && root.val != root.right.val)
return false;
count[0]++;
return;
}
return false;
}
18. Convert Sorted Array to Binary Search Tree(108. leetcode)
这里用到了分治思想
1.tree 的travesal 最终会回到 root
2.这里要用 low > high 作为return
public TreeNode sortedArrayToBST(int[] nums) {
if(nums == null || nums.length ==0) return null;
return helper(nums, 0, nums.length - 1);
}
public TreeNode helper(int[] nums, int low, int high) {
if(low > high) return null;
int mid = low + (high - low)/2;
TreeNode root = new TreeNode(nums[ mid]);
root.left = helper( nums, low, mid-1);
root.right - helper(nums, mid+1 , high);
return root;
}
19. Convert Sorted List to Binary Search Tree(109. leetcode)
- 问题点在于要找list 的medium -> 直接用 slow, 和 fast pointer
- 还有就是 要medium 前面的pointer -> 解决方法: 不用放mid 的前一个pointer, 直接把mid 传进去,然后让 下一层的mid 不能等于 tail
- base case : head == tail returun null
public TreeNode sortedListToBST(ListNode head) {
if(head == null) return null;
return toBST(head, null);
}
public TreeNode toBST(TreeNode head,TreeNode tail) {
TreeNode slow = head;
TreeNode fast = head;
if(head == tail) return null;
while(fast != tail && fast.next != tail) { /* 这里要写 tail, 而不是 null*/
fast = fast.next.next;
slow = slow.next;
}
TreeNode node = new TreeNode(slow.val);
node.left = toBST(head, slow);
node.right = toBST(slo.next. tail);
return node;
}
20. Closest Binary Search Tree Value(270. leetcode)
public int closestValue( TreeNode root, double target) {
int res ={ root.val};
helper(root, target, res);
return res[0];
}
public boolean helper(TreeNode root, double target, int[] res) {
if( root == null) return true;
if( Math.abs( root.val - target ) < Math.abs( res[0] - target))
res[0] = root.val;
return helper( root.left, target , res[0] ) && helper( root.right , target, res[0]);
}
20*(Hard). Closest Binary Search Tree Value II (272. leetcode)
- 用deque 的数据结构
- 用 Inorder 的算法遍历tree , 按顺序添加node, 放入deque
- 通过先 declare linkedlist , 再 assign 给 Dqeue , 达到实时更新
public List closestkValue(TreeNode root, double target, int k) {
List res = new LinkList<>();
if(root == null) return res;
Deque dq = (LinkedList) res;
recurInorder( root, target, dq, k);
return res;
}
public void recurInorder( TreeNode root, double target, Deque dq, int k){
if(root == null) return ;
recurInorder( root.left , target, dq, k);
if( dq.size() < k){
dq.offerLast( root.val);
} else if( root.val <= target){
dq.offerLast(root.val);
dq.pollFirst();
} else{
if( root.val - target < target - dq.pollFirst()){
dq.offerLast( root.val);
dq.pollFirst();
} else{
return;
}
}// else
recurInorder( root.right, target, dq, k);
}
21. Lowest Common Ancestor of a Binary Search Tree(235. leetcode)
- 要利用到BST 的特性
public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
if( root.val > p.val && root.val >q.val) return lowestCommonAncestor(root.left , p ,q);
if(root.val < p.val && root.val
22. Lowest Common Ancestor of a Binary Tree(236.leetcode)
- 这一题承接上面一题, 但是 tree 变成了 binary tree 而不是 BST, 所以不能用 BST 的特性
思路分析:
1.如果 p , q 在同一边,则另一边的 子树 就返回null。 我们就返回 在的一边 - 如果p ,q 在两边的子树,则返回当前的 parent。
public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
if( root == null || root == p.val || root == q.val) /* 每一层下来的情况, 是否要停顿 返回*/
return root;
TreeNode left = lowestCommonAncestor(root.left , p ,q); /* 遍历操作*/
TreeNode right = lowestCommonAncestor(root.right, p, q);
return left == null ? right : right== null ? left : root; // 返回后有了left, right 子树的情况 要如何选择返回值
}
23. Sum of Left Leaves(404.leetcode)
- 这题只 记录左边的 leaves
- 所以需要从parent 的 parent 的 位置去判定是否是左边的leaves
- right child 也有可能是 left leaf
public int sumOfLeftLeaves(TreeNode root) {
int ans = 0 ; /* 这里是 root 的部分*/
if( root == null) return 0;
if( root.left != null) {
if( root.left.left == null && root.left.rigth == null)
ans += root.left.val;
else
ans += sumOfLeaves( root.left );
}
ans += sumOfLeaves(root.right);
return ans;
}
24. Find Mode in Binary Search Tree(501. leetcode)
- 返回所有出现频率最高的nodes
- 因为相等的有可能 出现在左边也有可能出现在右边, 所以要按 increasing 的顺序遍历 tree 才能一下子连续遍历到相同的node , 所以要用in-order traversal. 进行遍历
- 注意BST 中”等于“的情况,
总结: 在BST 中 相同的node 一定都在左边, 所以要用 in-order traversal.
public class {
int previous = 0;
int max = 0;
int count = 0;
public int[] findMode( TreeNode root) {
if( root = null )
return new int[0]; /* 这里不能返回 null,而是要返回一个 长度为0 的array*/
LinkedList res = new LinkedList< Integer>();
Inorder(root , res);
int [] result = new int[ res.size()];
for( int i=0; i res) {
if( node == null) return;
Inorder( root.left, res);
if( root.val != previous) {
count = 0;
previous = root.val;
}
count ++;
if( count > max) {
max = count;
res.clear();
res.add(root.val);
}
else if( count == max) {
res.add( root.val);
}
Inorder( root.rigth, res);
}
}
25.Validate Binary Search Tree( 98. leetcode)
- 这里直接用 pre-oreder 的方式遍历,就可以了不需要 in-order 或 post-order
public boolean isValidBST(TreeNode root) {
return isValidBST( root, Long.MAX_VALUE, Long.MIN_VALUE);
}
public boolean isValidBST( TreeNode root, long maxValue, long minValue) {
if( root == null) return true;
if( root >= maxValue || root <= minValue) {
return false;
}
return isValidBST( root.left, root.val , minValue)
&& isValidBST( root.right, maxValue, root.val);
}
26.Binary Search Tree Iterator( 173.leetcode)
- overwrite a function
问题:
-1. 这个function 里的删除操作,是否会 修改了原来的树
解法: 这里用了 Dequeue 数据结构, 因为既可以从头插入, 又可以从尾部插入。更加便捷, 这里 Dequeue 需要由ArrayDeque, 或LinkedLIst 实现; 用in-order 的方式把node 从小到大 插入deque 的尾部
public class BSTIterator {
Deque dq;
public BSTIterator(TreeNode root) {
if( root == null) return;
dq = new ArrayDeque<>();
dq.pushAll(root);
}
private void pushAll(TreeNode node ) {
if( node == null) returnl
pushAll( node.left );
dq.offerLast( node.val );
pushAll( node.right );
}
public boolean hasNext() {
return !dq.isEmpty();
}
public int next() {
if( hasNext() )
return dq.pollFirst();
return -1;
}
}
27.Inorder Successor in BST( 285.leetcode)
-1. 在 BST 中找node, 或比这个node 大 或 比这个 node 小的 的node 的时候, 注意利用BST 的特性
-2. 当找到特定的node 之后想要返回当前的node, 可以用 return ( left != null) ? left : root
- Code walkthrough for Successor:
-1. First we go to exact path of node til end which we want to find out using BST property.
-2. Use back track, Consideration for every node while back track
-.(a). For every node if we backtrack from right side then simply return because successor will be its parent .
-(b). if we backtrack from left side, then successor will be either current node OR any successor found in left subtree.
方一: 用 recursion 的方法, 找到 .Inorder Successor
public TreeNode inorderSuccessor(TreeNode root, TreeNode p) {
if( root == null ) return null;
if( root.val < p.val ){
return inorderSuccessor( root.right , p);
}else {
TreeNode left = inorderSuccessor( root. left, p );
return ( left != null )? left : root;
}
}
用 recursion 的方法, 找到 Inorder predecessor
public TreeNode inorderPredecessor(TreeNode root, TreeNode p) {
if( root == null) return null;
if( root.val >= p.val) {
return inorderPredecessor( root.left, p);
} else {
TreeNode right = inorderPredecessor( root.right , p);
return ( right != null ) ? right : root;
}
}
28.Inorder Successor in BST II( 510. leetcode)
public Node inorderSuccessor(Node x) {
if( x.right == null ){
Node result = x.parent;
while( result != null && result.val < x.val)
result = result.parent;
return result;
} else {
Node result = x.right;
while(result. left != null )
result = result.left;
return result;
}
}
29. Diameter of Binary Tree( 543.leetcode)
int maxSum ;
public int diameterOfBinaryTree(TreeNode root) {
maxSum =0;
DFS(root);
return maxSum;
}
public int DFS( TreeNode node){
if( node == null) return 0;
TreeNode left = DFS(node.left);
TreeNode right = DFS(node.right);
maxSum = Math.max( maxSum, left+ right);
return Math.max(left, right) + 1;
}
30. N-ary Tree Preorder Traversal( 589.leetcode)
public List preorder(Node root) {
List res = new ArrayList<>();
DFS( root, res);
return res;
}
public void DFS( Node node , List res) {
if( root == null) return;
res.add( node.val);
if( node.children != null ) {
for( int i = 0; i< node.children.size(), i++){
DFS(node.children.get(i), res);
} // for
}// if
}
31. N-ary Tree Level Order Traversal( 429.leetcode)
33.N-ary Tree Postorder Traversal (590.leetcode)
public List postorder(Node root) {
List< Integer> res = new ArrayList<>();
postOrder(root, res);
return res;
}
public void postOrder( Node root, List) res{
if( root == null) return;
List group = root.children;
for(Node child : group){
postOrder(child, res);
}
res.add(root.val);
}
从这里考开始, 就是 tree 和 string 相互转化
34.Construct String from Binary Tree (606.leetcode)
- 这道题需要思考, 在哪一步加空格, 在那一步需要 trim, 不加“ ()”
方一:10ms, 最后才加括号 postorder 的手法
public String tree2str(TreeNode t) {
if( t == null) return;
String left = tree2str( t.left);
String right = tree2str(t.right);
if(left == "" && right == "")
return t.val +"";
if(left =="")
return t.val +" ()" + "(" + right +")";
if( right == "")
return t.val +" (" + left + ")" ;
return t.val + " ( "+ left + ")"+ "(" + right +")";
}
方二:7 ms
public String tree2str(TreeNode t) {
StringBuilder sb = new StringBuilder();
helper(t, sb);
return sb.toString();
}
public void helper( TreeNode t, StringBuilder sb) {
if( t == null) return ;
sb.append(String.valueOf(t.val))
if( t.left != null) {
sb.append("(");
helper(t.left, sb);
sb.append(")");
if( t.right != null) {
sb.append("(");
helper(t.right, sb);
sb.append(" )");
}
}
else if( t.right != null) {
sb.append(" ()");
sb.append(" (");
helper(t.right, sb);
sb.append(" )");
}
}
35.Construct Binary Tree from String (536.leetcode)
解题难点
-1. 区分“ ()”
-2. 在
class Solution {
int i = 0; // make i global
public TreeNode str2tree(String s) {
if( s == null || s.length() == 0) return null;
return dfs(s);
}
public TreeNode dfs(String s) {
TreeNode root = null;
if( s.charAt(i) != ')'){
root = new TreeNode( getInt(s));
}
TreeNode leftN = null, rightN = null;
if( i< s.length() && s.charAt(i) == '('){ // for the possible leftNode, if '(' met.
i ++;
leftN = dfs(s);
}
if( i< s.length() && s.charAt(i) == ' (') { // for the possible right, if '(' met.
i ++;
rightN = dfs(s);
}
// if not '(' it must be ')' or i==s.length()
// so we return the current stack
root.left = leftN;
root.right = rightN;
i ++; / *跑到 这一步, 说明 s.charAt(i) == ' ) ' , 所以要 i++ , 到right node */
return root;
}
public int getInt( String s){
StringBuilder sb = new StringBuilder();
while( i < s.length () && s.charAt(i) != ')' && s.charAt(i ) != "(" ){
sb.append( s.charAt(i) );
i ++;
}
int val = Integer.valueOf( sb);
return val;
}
}
36.Find Duplicate Subtrees (652.leetcode)
- 这是一道 找相同的 subtree 的题, 使用了 hashmap 的数据结构+ postorder 的遍历方法
public List findDuplicateSubtrees(TreeNode root) {
Map map = new HashMap<>();
List res = new ArrayList<>();
postOrder( map, res, root);
return res;
}
public String postOrder(Map map, List res, TreeNode root ) {
if( root == null) return "#";
String str = root.val + helper(map, res, root.left) + helper( map, res, root.right);
if( map. getOrDefault(str, 0) == 1) {
res.add(root);
}
map.put(str, map.getOrDefault( str, 0) + 1);
return str;
}
37.Serialize and Deserialize BST (449.leetcode)
- 把数字加入StringBilder(), 但是当空间不够时, 可以用 char, 而不是int, 因为char 只要4个byte
str.append( (char)( root.val + '0') ); - linkedlist, arraylist 都有addAll( ), 里面放List
- 解题思路: 1. 把tree 用 preorder 的形式遍历一遍, 用StringBuilder 把结果存起来
public String serialize(TreeNode root) {
StringBuilder sb = new StringBuilder();
serHelper(sb , root);
return sb.toString();
}
public void serHelper( StringBuilder sb , TreeNode root) {
if( root == null) sb.append(' #');
sb.append( ( char) (root.val + '0'));
serHelper( root.left);
serHelper( root.right);
}
int index;
public TreeNode deserialize(String data) {
return desHelper( data.toCharArray());
}
public TreeNode desHelper( char[] data) {
if( data[index] == '#' ) {
index ++;
return null;
}
TreeNode root = new TreeNode( data[index ++] - '0' );
root.left = desHelper(data);
root.right= desHelper(data);
return root;
}
38. Serialize and Deserialize Binary Tree(297.leetcode)
- 这一题 需要考虑到 root.val 可能是 2位数甚至 更多, 或者可能是负数
public class Codec {
private static final String spliter = ",";
public String serialize(TreeNode root) {
if( root == null) return null;
StringBuillder sb = new StringBuilder();
BuildString(sb, root);
return sb.toString();
}
public void BuildString(StringBuilder sb, TreeNode root ){
if( root == null) {
sb.append('#').apend(spliter);
return ;
}
sb.append( root.val).append(spliter);
BuildString(sb, root.left);
BuildString( sb, root.right);
}
public TreeNode deserialize(String data) {
Deque queue = new LinkedList<>();
queue.addAll( Arrays.asList( data.split(spliter)));
return buildTree(queue);
}
public TreeNode buildTree( Deque queue ) {
String val = queue.remove();
if( val.equals("#")) return null
TreeNode node = new TreeNode( Integer.valueOf( val));
node.left = buildTree( queue);
node.right= buildTree( queue);
return node;
}
}
40.Serialize and Deserialize N-ary Tree(428.leetcode)
- N-ary 里, 这个Node 不为
class Node {
public int val;
public List children;
public Node() {}
public Node(int _val,List _children) {
val = _val;
children = _children;
}
};
time complexity: 7ms
- N-ary 这里先建立list, 重要的是 children.add( dfs( str))
class Codec {
public String serialize(Node root) {
StingBuilder sb = new StringBuilder();
serDFS(root, sb);
return sb.toString();
}
public void serDFS(Node root, StringBuilder sb) {
if(root == null) return;
sb.append(root.val).append(' ');
for(Node child : root.children) {
serDFS(root, sb);
}
sb.append(") ");
}
public Node deserialize(String data) {
if( data == null || data.length() == 0) return null;
return desHelper( data.split(" "), new int[]{0});
}
public Node desHelper( String[] data , int[] cur) {
int index = cur[0];
if(index == data.length) return null;
List children = new ArrayList<>();
Node node = new Node(Integer.parseInt( data[index] ), children );
cur[0] =+ 1;
while( !data[cur].equals(")") ) {
children.add( desHelper( data , cur));
}
cur[0] ++;
return node;
}
}
41.Trim a Binary Search Tree( 669. leetcode)
- 这道题就是一边遍历tree, 一边trim BST 的结构
- 可以通过return 下一个 node 的val , 来删除current node, 从而改变树的结构
public TreeNode trimBST(TreeNode root, int L, int R) {
if( root == null ) return null;
if( root.val < L ) return trimBST(root.right, L, R);
if( root.val > R) return trimBST(root.left, L, R);
root.left = trimBST(root.left, L, R);
root.right = trimBST(root.right, L, R);
return root;
}
42.Cousins in Binary Tree( 993.leetcode)
- x,y 不能有common parent
- x, y 在相同 depth 上
- 解题思路: 分开判断 1. 是否有common parent; 2, 是否是相同depth
public boolean isCousins(TreeNode root, int x, int y) {
int depth1 = findDep(root, x );
int depth2= findDepth( root, y);
if( depth1 != depth 2)
return false;
return !sameParent( root, x, y);
}
public int findDep(TreeNode root, int x ) { /* 如何 return int */
if( root == null) return -1;
if( root.val == x ) return 0;
int l = findDep(root.left , x);
int r = findDep(root.right , x);
if( l == -1 && r == -1 ) return -1 ;
if( l == - 1)
return r + 1;
else
return l +1;
}
public boolean sameParent( TreeNode root, int x, int y){
if( root == null) return false;
boolean check = false;
if( root.left != null || root.right != null){
check = (root.left.val == x && root.right .val == y) ||
(root.right.val == x && root.left.val == y)
}
return check || sameParent( root.left, x, y) || sameParent(root.right , x, y);
}
43. Binary Tree Zigzag Level Order Traversal( 103.leetcode)
- java library : Collections.reverse(list);
public List> zigzagLevelOrder(TreeNode root) {
List> res = new ArrayList<>();
Deque queue = new LinkedList<>();
if(root == null) return res;
queue.offer(root);
int n = 0;
while( !queue.isEmpty()){
int size = 0;
List tmp = nre ArrayList<>();
for( int i =0; i< size; i++){
TreeNode node = queue.poll();
if( node.left != null) queue.offer(node.left);
if(node.right != null) queue.offer( node.right);
tmp.add(node.val);
}
if( (n & 1) == 0){
res.add( tmp);
} else {
Collections( tmp);
res.add(tmp);
}
n ++:
}
return res;
}
44.Construct Binary Tree from Preorder and Inorder Traversal(105. leetcode)
- 用 HashMap的数据结构 存inorder array, 这样方便找到root 的位置, 然后算出 leftLen 或rightLen
class Solution{
public TreeNode buildTree(int[] preorder, int[] inorder) {
Map map = new HashMap<>();
for( int i=0; i < inorder.length; i++){
map.put(inorder[i], i);
}
return helper(preorder, 0, preorder.length -1 , inorder, 0, inorder.length - 1, map);
}
private TreeNode helper(int[] preorder,int pStart , int pEnd,int[] inorder , int iStart, int iEnd , Map map ){
if( iStart > iEnd || pStart > pEnd) return null;
int pivot = map.get( preorder[pStart]);
int leftLen = pivot - iStart;
TreeNode node = new TreeNode( preorder[pStart]);
node.left = helper(preorder, pStart + 1, pStart + leftLen , inorder, iStart , pivot - 1);
node.right = helper(preorder, pStart+ leftLen + 1, pEnd, inorder, pivot+1, iEnd );
return node;
}
45.Construct Binary Tree from Inorder and Postorder Traversal(106. leetcode)
- 用 HashMap 的数据结构 存inorder array, 这样方便找到root 的位置, 然后算出 leftLen 或rightLen
public TreeNode buildTree(int[] inorder, int[] postorder) {
Map inorderMap = new HashMap<>();
int len = inorder.length;
for(int i=0; i < len; i++){
inorderMap.put(inorder[i] , i);
}
return helper(inorder, 0, inorder.length - 1, postorder, 0, postorder.length -1 , map );
}
public TreeNode helper(int[] inorder, int iStart, int iEnd, int [] postOrder, int pStart, int pEnd, Map map) {
if( iStart > iEnd || pStart > pEnd) return null;
TreeNode node = new TreeNode(postorder[ pEnd]);
int pivot = map.get(postorder[pEnd]);
int leftLen = pivot - iStart;
node.left = helper(inorder, iStart, pivot -1 , postorder, pStart, pStart+leftLen -1 , map);
node.right = helper(inorder, pivot + 1,iEnd, postorder, pStart +leftLen, pEnd -1 , map );
return node;
}
46.Flatten Binary Tree to Linked List(114. leetcode)
- 所tree 的问题的时候, 不仅可以从 inorder, preorder, postorder 入手, 还可以从遍历方向入手, 是先从左到右,还是从右到左遍历。
- 问题: 1. 在把左孩子插到右孩子的位置上时, 必须要把右孩子插到左孩子的尾部
- 这里有2种解决思路
1.通过改变遍历树的顺序, 在遍历书的同时,改变树的结构,直接把右边的chlid 插到左边的child 的下方
private TreeNode tail;
public void flattern(TreeNode root) {
if(root == null) return ;
flattern(root.right);
flattern(root.left);
root.right = tail;
root.left = null;
tail = root;
}
- 常规的方法, 不用改变树的遍历左右顺序
public void flattern(TreeNode root) {
if( root == null) return ;
flattern(root.left);
flattern(root.right);
TreeNode right = root.right;
root.right = root.left;
root.left = null;
while(root.right != null){
root = root.right;
}
root.right = right;
}
47.Flatten a Multilevel Doubly Linked List(430. leetcode)
- 因为child 的优先级高于next。 所以要先去到child 那一层, 改变树的结构
public Node flatten(Node head) {
if( head == null) return null;
Node child = flatten( head.child);
Node next = flatten(head.next);
if(child != null){
head.next = child;
head.child = null;
child.prev = head;
if( next ==null) return null;
Node tmp = head;
while( tmp.next != null) {
tmp = tmp.next;
}
tmp.next = next;
next.prev = tmp;
}
return head;
}
48.Populating Next Right Pointers in Each Node(116.leetcode)
- tree 是 full binary tree
- 用了 dummy node, prev node 和 cur node 对树进行修改
public Node connect(Node root) {
Node cur = root;
while( cur != null) {
Node dummy = new Node(0);
Node prev = dummy;
while( cur != null) {
if(cur.left != null){
prev.next = cur.left;
prev = prev.next;
}
if(cur.right != null) {
prev.next = cur.right;
prev = prev.next;
}
cur = cur.next;
}
cur = dummy.next;
}
return root;
}
49.Populating Next Right Pointers in Each Node II (117.leetcode)
- 解法同上一题一摸一样
50.Binary Tree Right Side View(199. leetcode)
- 一旦 遍历tree 就不能停止,必须遍历完整棵tree, 只能通过 过滤加入 res 的条件,才能得到正确的 res 。
- 用了 preorder 的遍历方法
- 增加 depth 变量, 若 depth == res.size() ,则 res.add(val)
public List rightSideView(TreeNode root) {
List res = new ArrayList<>();
preorder(res, root, 0);
return res;
}
public void preorder( List res, TreeNode root, int depth ){
if( root == null) return;
if(depth == res.size())
res.add(root.val);
preorder(res, root.right, depth+1);
preorder(res, root.left, depth + 1);
}
51.Kth Smallest Element in a BST(230.leetcode)
int sum;
public int kthSmallest(TreeNode root, int k) {
int [] res = {0};
inorder(root, k, res);
return res[0];
}
public void inorder(TreeNode root, int k, int[] res){
if(root == null) return;
inorder(root.left, k, res);
sum ++;
if(sum == k){
res[0] = root.val;
}
inorder(root.right, k, res);
}
52.Binary Tree Longest Consecutive Sequence(298.leetcode)
- 用preorder 的算法 + 一个static variable 记录max
int max;
public int longestConsecutive(TreeNode root) {
if ( root == null) return 0;
helper( root, 0, root.val);
return res;
}
public void helper (TreeNode root, int res , int target) {
if( root == null) return;
if( root.val == target)
res ++;
else
res = 1;
max = max > res ? max : res;
helper( root.left, res, target+1);
helper(root.right, res, target + 1);
}
53. Largest BST Subtree(333.leetcode)
- 这道题的难点在于, 不仅仅要检查parent ,child 的关系, 可能还要检查grandparent 的关系
- 这里不能用inorder 的原因是, 只能先知道左子树 是否 是BST tree, 但不知道右子树 是否是标准的BST tree, 所以不能贸然加parent
int max;
public int largestBSTSubtree(TreeNode root) {
if(root == null) return 0;
help(root);
return max;
}
public int[] helper(TreeNode root){
if( root == null) return new int[] {0, Integer.MAX_VALUE, Integer.MIN_VALUE};
int[] left = helper(root.left);
int[] right = helper(root.right);
if( left [0] == - 1 || right[0] == -1 || root.val <= left[2] || root.val >= right[1])
return new int[] {-1, 0,0};
max = max > (left[0] + 1+ rigth[0]) ? max : (left[0] + 1+ rigth[0]) ;
return new int[]{ (left[0] + 1+ rigth[0]) , Math.min(left[1], root.val), Math.max(right[2], root.val)};
}
54.House Robber III( 337.leetcode) !!!!!!
- 这里不仅仅 只有 root.val + grandchild 的可能性
- 解题思路: tree+ DP
public int rob(TreeNode root) {
int[] res = robSub(root);
return Math.max(res[0], res[1]);
}
private int[] robSub(TreeNode root) {
if (root == null) return new int[2];
int[] left = robSub(root.left);
int[] right = robSub(root.right);
int[] res = new int[2];
res[0] = Math.max(left[0], left[1]) + Math.max(right[0], right[1]);
res[1] = root.val + left[0] + right[0];
return res;
}
55.Find Leaves of Binary Tree(366.leetcode)
- 把tail 按顺序加入 res
- 这道题只要返回 每个node 在 res, 中的index 就可以了
- 注意点 : 要记得可以利用 res.size() 与 level 之间的关系
public List> findLeaves(TreeNode root) {
List> res = new ArrayList<>();
if( root == null) return res;
helper(root, res);
return res;
}
public int helper(TreeNode root, List> res){
if( root == null) return -1;
int left = helper(root.left, res);
int right = helper(root.right, res);
int maxLevel = Math.max(left, right) + 1;
if( res.size() < maxLevel + 1)
res.add(new ArrayList<>());
res.get(maxLevel).add(root.val);
return maxLevel;
}
56.Delete Node in a BST(450. leetcode)
- 删除BST tree 的一个node 以后, 先判断, 是否同时包含左右子树, 若都包含, 就把左子树最大的node 或 右子树 最大的node , 拿到要删除的这个node 的位置上。
public TreeNode deleteNode(TreeNode root, int key) {
if( root == null ) return null;
if(root.val == key){
if(root.left == null)
return root.right;
if(root.right == null)
return root.left;
TreeNode min = findmin(root.left);
root.val = min.val;
root.right = deleteNode(root.right, root.val);
}
if( root.val> key){
root.left = deleteNode(root.left, key);
}else{
root.right = deleteNode(root.right, key);
}
return root;
}
57.Most Frequent Subtree Sum(508. leetcode)
- 用 hashmap 存储 sum 和 次数
- list 存储 final result list
- max 次数
class Solution {
Map map;
List maxList;
int maxFreq;
public int[] findFrequentTreeSum(TreeNode root) {
if(root == null) return new int[0];
map = new HashMap();
maxList = new ArrayList();
helper(root);
int res[] = new int [ maxList.size()];
for(int i=0; i< res.size(); i++){
res[i] = maxList.get(i);
}
return res;
}
public int helper( TreeNode root){
if(root == null) return 0;
int sum = helper(root.left) + helper(root.right) + root.val;
int cur = map.getOrDefult(sum. 0) + 1;
if( cur > maxFreq){
maxFreq = cur;
maxList = new ArrayList<>();
maxList.add( sum);
} else if( cur == maxFreq){
maxList.add(sum);
}
map.put(sum, freq);
return sum;
}
}
58.Find Bottom Left Tree Value(513.leetcode)
class Solution {
int curLevel ;
int res;
public int findBottomLeftValue(TreeNode root) {
curLevel = -1;
post(root, 0);
return res;
}
public void post(TreeNode root, int level) {
if(root == null) return ;
if(curLevel < level){
res = root.val;
curLevel = level;
}
post(root.left, level + 1);
post(root.right, level + 1);
}
}
59.Find Largest Value in Each Tree Row(515.leetcode)
public List largestValues(TreeNode root) {
Deque queue = new LinkedList<>();
List res = new ArrayList<>();
if(root == null) return res;
queue.offer(root);
while(! queue.isEmpty()){
int size = queue.size();
int max = Integer.MIN_VALUE;
for(int i=0; i node.val? max: node.val;
if(node.left != null) queue.offer(node.left);
if(node.right != null) queue.offer(node.right);
}
res.add(max);
}
return res;
}
60.Binary Tree Longest Consecutive Sequence II(549. leetcode) 和 298 similar
- 找到最长的连续的path
- **问题点: ** consecutive path 可以是 递减的, 也可以递增 -> 解决思路 , function 传array; 用array 记录 当前inc, drc 的值。 inc + drc - 1 是path是 child + parent + child 的可能性
int max;
public int longestConsecutive(TreeNode root) {
if( root == null) return 0;
helper( root );
return max;
}
public int[ ] helper( TreeNode root) {
if( root == null) return new int[ ]{ 0,0};
int inc = 1, drc = 1;
if( root.left != null ){
int[] left = helper( root.left);
if( root.val == root.left.val - 1)
inc = left[ 0] + 1;
else if( root.val == root.left.val + 1)
drc = left[1] + 1;
}
if( root.right != null ){
int[] right = helper(root.right);
if( root.val == root.right.val -1 )
inc = Math.max( inc , right[0] + 1);
else if( root.val == root.right.val + 1)
drc = Math.max(drc , right[1] + 1)
}
max = Math.max( max, inc + drc - 1);
return new int [ ]{ inc, drc };
}
61.Kill Process(582. leetcode)
- 用了一个 HashMap: 存 ppid 和 所有直接对应的 pid
- 用了 一个 stack:存要删除的pid
- 用了一个 list : 存答案
public List killProcess(List pid, List ppid, int kill) {
Map> map = new HashMap<>();
for( int i=0; i< ppid.size(); i++){
map.putIfPresent( ppid.get(i) , new LinkedList<>());
map.get(ppid.get()).add(pid.get(i));
}
Stack stack = new Stack<>();
stack.add( kill);
while( !stack.isEmpty() ){
int cur = stack.pop();
res.add(cur);
List adjacencyList = map.get(cur);
if( adjacencyList == null) continue;
stack.addAll( adjacencyList );
}
return res;
}
62.Add One Row to Tree(623. leetcode)
- 这里 boolean 用来 indicate 现在在那个 branch 上, 是 left branch 还是 right branch
public TreeNode addOneRow(TreeNode root, int v, int d) {
return helper(root, v,d, true);
}
public TreeNode helper(TreeNode root, int v, int d, boolean left) {
if( root == null) {
if(d == 1 ) return new TreeNode( v);
return null;
}
if( d == 1){
TreeNode newNode = new TreeNode(v);
if( left)
newNode.left = node;
else
nedNode.right = node;
return newNode
}
node.left = helper( root.left, v, d-1, true);
node.right = helper(root.right, v, d -1 , false);
return node;
}
63.Maximum Binary Tree(654.leetcode) 重建树
- 找到 max,
public TreeNode constructMaximumBinaryTree(int[] nums) {
return helper( nums, 0 , nums.length -1);
}
public TreeNode helper(int[] nums, int prev, int tail){
if( prev > tail) return null;
if( prev == tail) return new TreeNode( nums[prev]);
int max = findMax( nums, prev , tail);
TreeNode node = new TreeNode( nums[max]);
node.left = helper( nums, prev, max -1);
node.right = helper(nums, max + 1 , tail);
return node;
}
64.Maximum Binary Tree(654.leetcode)
public TreeNode ConstructMaximumBinaryTree( int[] nums){
return helper( nums, 0 , nums.length -1 );
}
public TreeNode helper( int[ ] nums, int prev, int tail ){
if( prev > tail ) return null;
if(prev == tail) return new TreeNode(nums[prev]);
int max = findMax(nums, prev, tail);
TreeNode node = new TreeNode( max);
node.left = helper( nums, prev, max - 1);
node.right = helper( nums, max + 1, tail);
return node;
}
public int findMax( int[] nums, int prev, int tail){
int max= nums[prev];
int j = prev;
for( int i = prev ; i <= tail ; i++){
if( max < nums[ i]) {
max = nums[i];
j = i;
}
}
}
65.Maximum Width of Binary Tree(662. leetcode) 转化tree 到 list 从而求 distance 的类型
- 当我们要把 tree , 以list 的形式表现出来
- left child: 是-> parent's index*2
- right child 是 -> parent's index *2 +1
- 解题思路: 把 tree 转换成 list 的形, 通过计算 每层 leftmost node index 与 current index 的距离, 得到最大width
int max ;
public int widthOfBinaryTree( TreeNode root){
List list = new ArrayList<>();
helper( root, list, 0,0);
return max;
}
public void helper( TreeNode root, List lefts, int level , int index){
if(root == null) return null;
if(level == lefts.size()) /* 进入下一层level*/
lefts.add(index);
int cur = index - lefts.get(level) + 1; /* 同当前index 减去 同level 的leftmost node*/
max = max > cur ? max : cur;
helper( root.left, lefts, level + 1, index *2 );
helper( root.right, lefts, level + 1, index*2 + 1);
}
65.Equal Tree Partition(663. leetcode)
- 这道题要计算 sum, 然后查看 移除 subtree 以后的sum
- 注意点: 指针可以直接比较
- 解题思路: 1. 先找到 整棵树的totalSum , 2 然后用 postorder check
是否存在 equal tree 。 3. boolean 值, 可以作为static variable
public class Solution {
public int findKthLargest(int[] nums, int k) {
if (nums == null || nums.length == 0) {
return -1;
}
return quickSelect(nums, 0, nums.length - 1, nums.length - k + 1);
}
private int quickSelect(int[] nums, int start, int end, int k) {
if (start == end) {
return nums[start];
}
int mid = start + (end - start) / 2;
int pivot = nums[mid];
int i = start, j = end;
while (i <= j) {
while (i <= j && nums[i] < pivot) {
i++;
}
while (i <= j && nums[j] > pivot) {
j--;
}
if (i <= j) {
int temp = nums[i];
nums[i] = nums[j];
nums[j] = temp;
i++;
j--;
}
}
if (start + k - 1 <= j) {
return quickSelect(nums, start, j, k);
} else if (start + k - 1 >= i) {
return quickSelect(nums, i, end, k - i + start);
}
return nums[j + 1];
}
}
66.Number of Islands(200. leetcode)
- 这的题的DFS 算法最快, 以下是DFS 解法, union-find 解法 在 union-find 版面
public int numIslands(char[][] grid){
int c = 0;
for( int i=0;i= grid.length || j > grid[0].length || grid[i][j] == ' 0') return ;
grid[ i ][ j ] = '0';
marker( i - 1, j , grid);
marker( i + 1, j , grid);
marker( i , j + 1, grid);
marker( i , j -1 , grid);
}
67.Closest Leaf in a Binary Tree(742. leetcode)
思路: 用post - order 遍历 , parent 记录 左子树 和 右子树 的 最短level , 在 post - order 的位置判断 是否已经reach
解题思路: 用class 来pass level 和 distance 参数, 这样一次遍历就可以了, target 到每个 ancestor ‘s dist + leaf 's level .
class Solution {
class res {
TreeNode leaf ;
int level;
boolean contains;
public res(TreeNode node, int level){
leaf = node;
this.level = level;
}
public res(){}
}
private int distance = Integer.MAX_VALUE;
private int minRes = 0; // 封装
public int findClosestLeaf(TreeNode root, int k) {
helper(root, k);
return minRes;
}
private res helper( TreeNode root , int target ){
if( root == null ) return new res(null, Integer.MAX_VALUE);
res left = helper(root.left, target);
res right = helper(root.right, target);
res result = new res();
if(left.leaf == null && right.leaf == null){
result.leaf = root;
result.level = 1;
}
else{ /* 取离自己近的 level*/
result.level = left.level < right.level ? left.level + 1 : right.level + 1;
result.leaf = left.level < right.level ? left.leaf : right.leaf ;
}
// 处理完 result ; 接下来进行判断
boolean find = false;
if(root.val == target){ // parent 就是 target , 刚刚找到target
result.dist = 0;
result.contains = true;
find = true;
}else if( left.contains || right.contains ){ // 在孩子的部分找到target
find = true;
result.contains = true;
if(left.contains) result.dist = left.dist + 1;
if(right.contains) result.dist = right.dist + 1;
}
if(find){
if(result.dist + result.level < distance){
distance = result.dist + result.level;
minRes = result.leaf.val
}
}
return result;
}
68.Convert Binary Search Tree to Sorted Doubly Linked List(426. leetcode)
- 这道题还是主要处理 leaf 的位置, 把 leave 上的 null 都处理了
- 如何处理 隔了 n 的 level 的 调整 ----> 使用dummy node , prev ,记录上一个node
Node prev;
public Node treeToDoublyList(Node root) {
if(root == null) return null;
Node dummy = new Node(0, null, null);
prev = dummy;
helper(root);
prev.right = dummy.right;
dummy.right.left = prev;
return dummy.right;
}
public void helper(Node cur){
if(cur == null) return;
helpre(cur.left);
prev.right = cur;
cur.left = prev;
prev = cur;
helper(cur.right);
}
69.Binary Tree Pruning(814. leetcode)
public TreeNode pruneTree(TreeNode root) {
helper(root);
return root;
}
public boolean helper( TreeNode root){
if(root == null) return false;
if(root.left == null && root.right ==null){
if(root.val == 1) return true;
return false;
}
boolean left = helpert(root.left);
boolean right = helper(root.right);
if(!ledt || !right){
if(!left) root.left = null;
if(!right ) root.right = null;
if(root.val = 1) return true;
else return left || right;
}
return left || right;
}
70.All Nodes Distance K in Binary Tree(863. leetcode)
-思路: 直接存入distance 到 HashMap + dfs
Map map ;
public List distanceK(TreeNode root, TreeNode target, int K) {
map = new HahsMap<>();
List res = new ArrayList<>();
find(root, target);
dfs(root, target, K, 0 , res)
return res;
}
public int find( TreeNode root, TreeNode target){
if( root == null) return -1;
if(target == root){
map.put(root, 0);
return 0;
}
int left = find(root.left, target);
if(left >=0 ){
map.put(root, left + 1);
return left + 1;
}
int right = find(root.right , target)
if(right >=0){
map.put(root, right + 1);
return right + 1;
}
return -1;
}
public void dfs(TreeNode root, TreeNode target, int K , int length , List res){
if( root == null) return ;
if(map.contains(root)) length = map.get(root);
if(length == K) res.add(root);
dfs(root.left, target, K, length + 1, res);
dfs(root.right , target, K , length + 1, res);
}
71.Smallest Subtree with all the Deepest Nodes(865.leetcode)
- 这道题和寻找公共祖先 相类似,
- return left == null ? right : (right == null ? left : root); -> 用来返回 公共祖先
- 解题思路: 1. 找到 Maxdepth , 2. 找到后return 满足要求的node , 然后return parent
public TreeNode subtreeWithAllDeepest(TreeNode root) {
int depth = findDep(root);
TreeNode node = findPar(root, depth, 1);
return node;
}
public int findDep( TreeNode root){
if(root == null) return 0;
int left = findDep(root.left);
int right = findDep(root.right);
retutn left > right ? left + 1 : right + 1;
}
public TreeNode findPar(TreeNode root, int depth, int level ){
if(root == null) reutrn null;
if(level == depth ) return root;
TreeNode left = findPar(root.left, depth, level + 1);
TreeNode right = findPar( root.right , depth , level + 1);
return left == null ? right : (right == null ? left : root);
}
73.Construct Binary Tree from Preorder and Postorder Traversal (889.leetcode)
-解题思路 1. loop on pre array and construct node one by one
- "stack" save the current path of tree
- node = new TreeNode(pre[i]) , if not left child , add node to the left .otherwise add to the right
- if we meet a same value in the pre and post, it means we complete the cnstruct for the current subtree . we pop it from stack.
complexity : O(n) time, O(N) space
public TreeNode constructFromPrePost(int[] pre, int[] post) {
Deque que = new LinkedList<>();
TreeNode root = new TreeNode(pre[0]);
que.offer(root);
for(int i =1, j=0; i
74.All Possible Full Binary Trees (894. leetcode)
解题思路: 用hashmap, 有dp 思想
- full tree 定义: every parent has 0 or 2 children
Map> map = new HashMap<>();
public List allPossibleFBT(int N) {
if( !map.containsKey( N) ){
List ans = new LinkedList<>();
if( N == 1) {
ans.add( new TreeNode(0));
}else if( N % 2 == 1){
for(int x = 0; x < N ; x ++){
int y = N -1 - x;
for(TreeNode left : allPossibleFBT( x)){
for(TreeeNode right : allPossibleFBT(y)){
TreeNode node =new TreeNode(0);
node.left = left;
node.right = right;
ans.add(node);
} // for right
} // for left
} // for
}// else if
map.put(N, ans);
}
return map.get(N);
}
75. Complete Binary Tree Inserter( 919. leetcode)
- Deque 有method getFirst(), getLast(), pollFirst() .... , 不论是 new LinkedList<>, 或是ArrayDeque<>
- complete tree: 每个level 从左向右填满
class CBTInserter {
TreeNode root;
Deque que;
public CBTInserter(TreeNode root) {
que = new LinkedList<>();
this.root = root;
que.add(root);
while(que.size != 0){
if(que.peekFirst().left != null && que.peek().right != null ){
que.offer( que.peek().left);
que.offer(que.peek().right);
que.poll();
} else break;
}
}
public int insert(int v) {
TreeNode node = new TreeNode(v);
TreeNode p = que.peek();
if(que.peek().right == null){
que.peek().right = node;
que.offer( que.peek().left );
que.offer(que.peek().right);
que.poll();
} else {
que.peek().left = node;
}
return p;
}
public TreeNode get_root() {
return root;
}
}
76. Flip Equivalent Binary Trees(951.leetcode)
public boolean flipEquiv(TreeNode root1, TreeNode root2) {
if( root1 == null && root2 == null ) return true;
if( root1 == null T@ !)
}