1. 重建树
  2. 遍历树

========================================================

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<List<Integer>> levelOrderBottom(TreeNode root) {
    List<List<Integer>> res = new ArrayList<>();
    DFS( res, root,0);
    return res;
}

public void BFS(List<List<Integer>> 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<List<Integer>> levelOrderBottom(TreeNode root) {
            Queue<TreeNode> queue = new LinkedList<>();
            List<List<Integer>> res = new LinkedList<>();
            if( root == null) return res;
            queue.offer(root);
            while( !queue.isEmpty() ) {
                int size = queue.size();
                List<Integer> 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<Double> averageOfLevels(TreeNode root) {
      Queue<TreeNode> 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<size;i++) {
                if(queue.peek().left != null) queue.offer( queue.peek().left);
                if(queue.peek().right != null) queue.offer(queue.peek().right);
                sum += queue.poll().val;
            }
            res.add(sum /size);
       }
        return res;
}
3.Binary Tree Level Order Traversal (102.leetcode)
  • 第三题 和 第一题的区别是,在res 里的顺序, 所以也就是 加入结果的时候 是插在res 的头部, 还是尾部
 public List<List<Integer>> levelOrder(TreeNode root) {
    List<List<Integer>> res = new ArrayList<>();
    DFS(res; root, 0);
     return res;
}
public void DFS(List<List<Integer>> 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<List<Integer>> pathSum(TreeNode root, int sum)  {
    List<List<Integer>> res = new ArrayList<>();
    backtracking(TreeNode root, int sum,res, new ArrayList<>());
    return res;
}
public void backtracking(TreeNode root, int sum, List<List<Integer>> 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<Integer, Integer> map = new HashMap<Integer, Integer>();
    return verify(root, sum, map, cur);
}
public int verify(TreeNode root, int sum, Map<Integer, Integer> 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<Integer, Integer> 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, 以及筛选

  1. 左子树 或 右子树 的total sum 能通过 maxValue 记录, 然后再和 上一个level 比较
  2. 以及当从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

  1. 需要一个参数记录 longestLength -> longestLength
  2. 还需要一个参数记录current length -> resl 记录left's length , resR 记录 resR's length
  3. 从上向下遍历, 从下向上(从下至上缩小选择范围)

没有注意的点

  1. 如果因为有 longestLength 记录最长的path,所以 resL, resR, 就用来记录当前的path 不用是最长的, 只是记录当前状态
    2.比较的时候,不要忘记有 left + right +node.val 的可能性
  2. 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<String> binaryTreePaths(TreeNode root) {
    List<String > 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<String> 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)
  1. 注意return 是 ||, 还是 &&
  2. 寻找的换 ||
  3. 检查树是否一样的话, 用&&
    解题思路: 先遍历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)

解题思路

  1. 当左边和右边孩子的值,都等于parent 的时候, count ++; 其余时候都不count++
  2. 当任意一边子树是null 时,是比较parent 与剩余一边的孩子的值, 相同则count++
  3. 当个两个 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)
  1. 问题点在于要找list 的medium -> 直接用 slow, 和 fast pointer
  2. 还有就是 要medium 前面的pointer -> 解决方法: 不用放mid 的前一个pointer, 直接把mid 传进去,然后让 下一层的mid 不能等于 tail
  3. 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<Integer> closestkValue(TreeNode root, double target, int k) {
    List<Integer> res = new LinkList<>();
    if(root == null) return res;
    Deque<Integer> dq = (LinkedList) res;
    recurInorder( root, target, dq, k);
    return res;
}

public void recurInorder( TreeNode root, double target, Deque<Integer> 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)
  1. 要利用到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 <q.val) return lowestCommonAncestor(root.right, p, q);
    return root;
}
22. Lowest Common Ancestor of a Binary Tree(236.leetcode)
  1. 这一题承接上面一题, 但是 tree 变成了 binary tree 而不是 BST, 所以不能用 BST 的特性
    思路分析
    1.如果 p , q 在同一边,则另一边的 子树 就返回null。 我们就返回 在的一边
  2. 如果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)
  1. 这题只 记录左边的 leaves
  2. 所以需要从parent 的 parent 的 位置去判定是否是左边的leaves
  3. 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)
  1. 返回所有出现频率最高的nodes
  2. 因为相等的有可能 出现在左边也有可能出现在右边, 所以要按 increasing 的顺序遍历 tree 才能一下子连续遍历到相同的node , 所以要用in-order traversal. 进行遍历
  3. 注意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<Integer> res = new LinkedList< Integer>();
      Inorder(root , res);
      int [] result = new int[ res.size()];
      for( int i=0; i<res.size(); i++){
          result[i] = res.get(i);
      }
      return result;
  }
  public void Inorder(TreeNode root, LinkedList<Integer> 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)
  1. 这里直接用 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)
  1. overwrite a function
    问题:
    -1. 这个function 里的删除操作,是否会 修改了原来的树
    解法: 这里用了 Dequeue 数据结构, 因为既可以从头插入, 又可以从尾部插入。更加便捷, 这里 Dequeue 需要由ArrayDeque, 或LinkedLIst 实现; 用in-order 的方式把node 从小到大 插入deque 的尾部
public class BSTIterator {
  Deque<Integer> 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<Integer> preorder(Node root) { 
    List<Integer> res = new ArrayList<>();
    DFS( root, res);
    return res;
}
public void DFS( Node node , List<Integer> 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<Integer> postorder(Node root) {
  List< Integer> res = new ArrayList<>();
   postOrder(root, res);
  return res;
}

public void postOrder( Node root, List<Integer>) res{
   if( root == null) return;
  List<Node> group = root.children;
  for(Node child : group){
     postOrder(child, res); 
  }
   res.add(root.val);
}

从这里考开始, 就是 tree 和 string 相互转化

34.Construct String from Binary Tree (606.leetcode)
  1. 这道题需要思考, 在哪一步加空格, 在那一步需要 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<TreeNode> findDuplicateSubtrees(TreeNode root) {
  Map <String , Integer> map = new HashMap<>();
  List<TreeNode> res = new ArrayList<>();
  postOrder( map, res, root);
   return res;
}

public String postOrder(Map <String , Integer> map,   List<TreeNode> 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<String> queue = new LinkedList<>();
    queue.addAll( Arrays.asList( data.split(spliter)));
    return buildTree(queue);
}
public TreeNode buildTree(   Deque<String> 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<Node> children;
    public Node() {}
    public Node(int _val,List<Node> _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<Node> 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<List<Integer>> zigzagLevelOrder(TreeNode root) {
    List<List<Integer>> res = new ArrayList<>();
    Deque<TreeNode> queue = new   LinkedList<>();
    if(root == null) return res;
    queue.offer(root);
    int n = 0;
    while( !queue.isEmpty()){
        int size = 0;
        List<Integer> 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<Integer , Integer> 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<Integer , Integer> 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<Integer , Integer> 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<Integer, Integer> 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;
}
  1. 常规的方法, 不用改变树的遍历左右顺序
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<Integer> rightSideView(TreeNode root) {
  List<Integer> res = new ArrayList<>();
  preorder(res, root, 0);
  return res;
}
public void preorder(  List<Integer> 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<List<Integer>> findLeaves(TreeNode root) {
    List<List<Integer>> res = new ArrayList<>();
    if( root == null) return res;
    helper(root, res);
    return res;
}

public int helper(TreeNode root, List<List<Integer>> 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<Integer, Integer> map;
List<Integer> maxList;
int maxFreq;
    public int[] findFrequentTreeSum(TreeNode root) {
        if(root == null) return new int[0];
        map = new HashMap<Integer, Integer>();
        maxList = new ArrayList<Integer>();
        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<Integer> largestValues(TreeNode root) {
        Deque<TreeNode> queue = new LinkedList<>();
        List<Integer> 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<size; i++){
                TreeNode node = queue.poll();
                max = max > 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<Integer> killProcess(List<Integer> pid, List<Integer> ppid, int kill) {
    Map<Integer, List<Integer>> 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<Integer> stack = new Stack<>();
    stack.add( kill);
    while( !stack.isEmpty() ){
        int cur = stack.pop();
        res.add(cur);
        List<Integer> 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<Integer> list = new ArrayList<>();
     helper( root, list, 0,0);
    return max;
}
public void helper( TreeNode root, List<Integer> 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; i++){
        for( int j=0; j<grid[0].length; j++){
            if( grid[ i ][ j] == ' 1 ') {
                  marker( i , j , grid);
                  c ++;
            }
        }
    }
    return c; 
}

public void marker( int i, int j, char[][] grid){
    if( i < 0 || j < 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<TreeNode , Integer> map ;
public List<Integer> distanceK(TreeNode root, TreeNode target, int K) {
    map = new HahsMap<>();
    List<Integer> 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<Integer> 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

  1. "stack" save the current path of tree
  2. node = new TreeNode(pre[i]) , if not left child , add node to the left .otherwise add to the right
  3. 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<TreeNode> que = new LinkedList<>();
    TreeNode root = new TreeNode(pre[0]);
    que.offer(root);
    for(int i =1, j=0; i<pre.length ; i++){
        TreeNode node = new TreeNode(pre[i]);
        while(post[j] == que.getLast().val){
            que.pollLast(); 
            j ++;
        }
        if(que.getLast().left == null) que.getLast().left = node;
        else 
            que.getLast().right = node
        que.offer(node);
    }
    return que.getFirst();
}
74.All Possible Full Binary Trees (894. leetcode)

解题思路: 用hashmap, 有dp 思想

  • full tree 定义: every parent has 0 or 2 children
Map<Integer, List<TreeNode>> map   = new HashMap<>();
public List<TreeNode> allPossibleFBT(int N) {
    if( !map.containsKey( N) ){
        List<TreeNode > 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<TreeNode> 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@ !)
 }
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 199,711评论 5 468
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 83,932评论 2 376
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 146,770评论 0 330
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 53,799评论 1 271
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 62,697评论 5 359
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,069评论 1 276
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,535评论 3 390
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,200评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,353评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,290评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,331评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,020评论 3 315
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,610评论 3 303
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,694评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,927评论 1 255
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,330评论 2 346
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 41,904评论 2 341

推荐阅读更多精彩内容