刷題筆記
常用方法
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找二叉查找樹的數目
分析:每一個節點都可以作爲頭結點,則
而對於給定頭結點爲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 的一些語法