刷题笔记
常用方法
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] 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 的一些语法