前言
在本科毕设结束后,我开始刷卡哥的“代码随想录”,每天一节。自己的总结笔记均会放在“算法刷题-代码随想录”该专栏下。
代码随想录此题链接
题目
略
1.递归的思想
思路(定义变量)
- TreeNode 树节点的类
- ArrayDeque 作为遍历栈:记录访问元素的顺序
- 封装结果的List< Integer>:记录处理元素的顺序
- 中序还需要一个树节点的类的遍历指针,因为中序处理元素和遍历元素的顺序不相同。
通解思路
处理元素意为,将元素的按照顺序输出到List< Integer>中。
前序:处理元素的顺序和访问元素的顺序相同,访问当前元素时即把当前元素处理(即当前元素val加入到List< Integer>中),并按“右、左”的顺序将当前节点的孩子节点加入到ArrayDeque 遍历栈中。(因为遍历栈弹出
的顺序跟入栈的顺序正好相反,所以弹出的顺序希望是“左、右”,输入的顺序就得是“右、左”)
继续循环的条件是,只要栈不为空。
后序:前序输出的顺序是“中、左、右”;后序是“左、右、中”;
前序可以先将左右顺序更换,变成“中、右、左”,然后整体倒序,“左、右、中”,此时顺序即为后序的顺序。
继续循环的条件是,只要栈不为空。
中序:处理元素的顺序和访问元素的顺序不同。所以需要添加一个树节点类型的遍历指针,来指向当前所访问的树节点。
继续循环的条件也与前序和后序不同:当前树节点类型指针指向不为空或者栈不为空
循环时只有两种情况,1.当前访问的节点不为空,则将当前节点加入栈中,并且指针移向他的左孩子;2.当前节点为空,说明之前加入栈(此时的栈顶元素)的树节点为此时需要处理的元素,即弹出栈顶元素,并将其的val输出到List< Integer>中,且继续让指针指向他的右孩子。
2. 本题思路分析:
3. 算法实现
- 代码:
统一的树节点类
public class TreeNode {
int val;
TreeNode left;
TreeNode right;
TreeNode() {}
TreeNode(int val) { this.val = val; }
TreeNode(int val, TreeNode left, TreeNode right) {
this.val = val;
this.left = left;
this.right = right;
}
}
前序
public List<Integer> preorderTraversal(TreeNode root) {
//迭代法
List<Integer> result = new ArrayList<>();
if(root == null) return result;
Deque<TreeNode> stack = new ArrayDeque<>();
stack.push(root);
while(!stack.isEmpty()){
TreeNode cur = stack.pop();
result.add(cur.val);
if(cur.right != null){
stack.push(cur.right);
}
if(cur.left != null){
stack.push(cur.left);
}
}
return result;
}
中序
public List<Integer> inorderTraversal(TreeNode root) {
List<Integer> result = new ArrayList();
Deque<TreeNode> stack = new ArrayDeque();
TreeNode cur = root;
while(!stack.isEmpty() || cur != null){
if(cur != null){
stack.push(cur);
cur = cur.left;
}else{
cur = stack.pop();
result.add(cur.val);
cur = cur.right;
}
}
return result;
}
后序
public List<Integer> postorderTraversal(TreeNode root) {
List<Integer> result = new ArrayList();
if(root == null){
return result;
}
Deque<TreeNode> stack = new ArrayDeque();
stack.push(root);
TreeNode cur = new TreeNode();
while(!stack.isEmpty()){
cur = stack.pop();
result.add(cur.val);
if(cur.left != null){
stack.push(cur.left);
}
if(cur.right != null){
stack.push(cur.right);
}
}
Collections.reverse(result);
return result;
}
4. pop函数的算法复杂度
树的节点数量为n
空间复杂度:O(n)
时间复杂度:O(n)
5. 算法坑点
略