leetcode-樹

刷題筆記

常用方法

DFS

樹的DFS遍歷:利用stack
例子:

  • 題目104:Maximum Depth of Binary Tree
public int maxDepth(TreeNode root) {
    if(root == null) {
        return 0;
    }
    
    Stack<TreeNode> stack = new Stack<>();
    Stack<Integer> value = new Stack<>();
    stack.push(root);
    value.push(1);
    int max = 0;
    while(!stack.isEmpty()) {
        TreeNode node = stack.pop();
        int temp = value.pop();
        max = Math.max(temp, max);
        if(node.left != null) {
            stack.push(node.left);
            value.push(temp+1);
        }
        if(node.right != null) {
            stack.push(node.right);
            value.push(temp+1);
        }
    }
    return max;
}
  • 111:Minimum Depth of Binary Tree跟上面的幾乎一致,但是將max換成了min
  • 關於優化解法—對於求最小而言,與最大不同,採用BFS能夠更快的實現最終效果,而DFS則需要遍歷所有的節點,因此對於Minmum而言,還是採用BFS會更好。

BFS

  • 樹的BFS遍歷:利用Queue
  • 104:
public int maxDepth(TreeNode root) {
    if(root == null) {
        return 0;
    }
    Queue<TreeNode> queue = new LinkedList<>();
    queue.offer(root);
    int count = 0;
    while(!queue.isEmpty()) {
        int size = queue.size();
        while(size-- > 0) {
            TreeNode node = queue.poll();
            if(node.left != null) {
                queue.offer(node.left);
            }
            if(node.right != null) {
                queue.offer(node.right);
            }
        }
        count++;
    }
    return count;
}
  • 102 Binary Tree level Order:將樹以層次表達出來,按照上面BFS做出適當修改即可(注意可以用size來表明每一行的node)
  • 199Binary Tree Right Side View:同樣的層次化表示,只要先offer左邊結點,就能夠保證每一層的最右結點永遠是最後一個poll的,利用這個特點將其加入結果當中即可。

與中序/後序/前序有關題目

  • 106 Construct Binary Tree from Inorder and Postorder Traversal
    這個題目的思路是比較簡單的,只需要考慮自己人工轉換的時候採取的思路即可,即把後序的最後一個當做根節點,同時劃分中序,然後進行遞歸即可。問題在於初始想法爲構造出新的inorder與postorder,無論是空間複雜度或者是可讀性都很差。這裏對於inorder和postorder都不做改變,但是用index來進行劃分是一種更好的方法。
class Solution {
    public TreeNode buildTree(int[] inorder, int[] postorder) {
        return buildTree(inorder,inorder.length-1,0,postorder,postorder.length-1);
    }
    private TreeNode buildTree(int[] inorder,int iS,int iE,int[] postorder,int pS){
        if(pS<0||iS<iE){return null;}
        
        
        TreeNode root =new TreeNode(postorder[pS]);
        int Rindex = iS;//找到根節點所在的位置從而進行劃分
        for (int i = iS; i >= iE; i--) {
      if (inorder[i] == postorder[pS]) {
       Rindex = i;
       break;
  }
 }
        
 root.right = buildTree(inorder, iS, Rindex + 1, postorder, pS-1);
 root.left = buildTree(inorder, Rindex - 1, iE, postorder, pS - (iS - Rindex) -1);
 return root;
       

DP

DP的實際特性即爲分解問題,此處做的題目還不夠多,後續補充ing

  • 96:Unique Binary Search Trees 找到給定數目的node找二叉查找樹的數目
    分析:每一個節點都可以作爲頭結點,則
    G[n]=T[1]+....T[n]G[n] =T[1]+....T[n]
    而對於給定頭結點爲i的二叉查找樹,其實等於1~i-1構成的查找樹的數目*i+1~n構成的數目
    則最終可以表示爲如下格式
public int numTrees(int n) {
  int [] G = new int[n+1];
  G[0] = G[1] = 1;
    
  for(int i=2; i<=n; ++i) {
    for(int j=1; j<=i; ++j) {
      G[i] += G[j-1] * G[i-j];
    }
  }
  return G[n];
}
  • 95Unique Binary Search Trees II 給出所有的二叉查找樹(不僅僅是數目)

Recursion

因爲樹的特性,很多題目都能夠用遞歸來解決。重點在於分析問題能不能有分解到下一層次的特徵。
比較典型的包括

  • 104Maximum Depth of Binary Tree(找到子樹的最大depth遞歸即可)
  • 100 Same Tree
class Solution {
    public boolean isSameTree(TreeNode p, TreeNode q) {
        if(p==null&&q!=null) return false;
        if(p==null||q==null) return true;
      
        if(p.val==q.val)
        return isSameTree(p.left,q.left)&&isSameTree(p.right,q.right);
        else return false;    
        
    }
}

特殊解法

124 Binary Tree Max Path Sum

這個題目特殊的點在於設置了一個MAX的全局變量。主要思路爲:對於每一個node,如果他是max path 上的node,那麼存在兩種情況,node爲最高點,那麼此時計算即爲

Math.max(maxValue,left+right+node.val);

否則這個節點不是最高點,則一定是單邊(最高節點爲父節點),只能選擇left/right 一邊,否則矛盾。return後爲recursion做準備

return Math.max(right+left)+node.val;

完整代碼

public class Solution {
    int maxValue;
    
    public int maxPathSum(TreeNode root) {
        maxValue = Integer.MIN_VALUE;
        maxPathDown(root);
        return maxValue;
    }
    
    private int maxPathDown(TreeNode node) {
        if (node == null) return 0;
        int left = Math.max(0, maxPathDown(node.left));
        int right = Math.max(0, maxPathDown(node.right));
        maxValue = Math.max(maxValue, left + right + node.val);
        return Math.max(left, right) + node.val;
    }
}

95

99

注意事項/分析代辦

  • 關於時空複雜度的問題
  • 關於JAVA 的一些語法
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章