题目链接:
144. 二叉树的前序遍历(简单)
145. 二叉树的后序遍历(简单)
算法原理:
在 Java数据结构------7.二叉树《干货笔记》中二叉树的遍历部分有详解,另外在其中 OJ 面试题部分还有非递归解法(借助栈实现,核心思路见下方代码中的注释部分)
144题:前序遍历
解法一:递归
0ms击败100.00%
时间复杂度O(N)
解法二:栈
1ms击败32.99%
时间复杂度O(N)
145题:后序遍历
解法一:递归
0ms击败100.00%
时间复杂度O(N)
解法二:栈
1ms击败32.99%
时间复杂度O(N)
在这里如果我们只是简单仿照着前序遍历的部分写,会发现出现一些问题👇
java/** * Definition for a binary tree node. * 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; * } * } */ class Solution { //145. 二叉树的后序遍历 //解法二:栈 List<Integer> list=new ArrayList<>(); public List<Integer> postorderTraversal(TreeNode root) { if(root==null) return list; Stack<TreeNode> stack=new Stack(); TreeNode cur=root; while(cur!=null||!stack.isEmpty()){ while(cur!=null){ stack.push(cur); cur=cur.left; } //由于往左走之后要打印右边 //所以需要先peek()一下,获取到右边的节点 //因为弹出去之后,右边的就获取不到了,就丢了 TreeNode top=stack.peek(); if(top.right==null){ list.add(top.val); stack.pop(); }else{ cur=top.right; } } return list; } }为什么呢??拿下面这个二叉树距离👇
当代码执行到 D 的时候,会发现:
D 不为空,D 入栈,cur 拿到 D 的左侧,此时栈:A、B、D
top 拿到栈顶 D ,发现 D 的右侧不为空(有个 K ),于是 cur 拿到 K
cur 不为空,K 入栈,cur 拿到 K 的左侧,此时栈:A、B、D、K
cur 为空,top 拿到栈顶 K,发现 K 的右侧为空,打印 K,弹出 K,此时栈顶:A、B、D
再进入循环:重点来了!!
cur 还是空,top 又拿到了栈顶 D,发现 D 的右侧不为空(有个 K )......
于是就在 D 和 K 之间形成了死循环~~
问题就出现在:D 的右边已经打印过了,回到 D 之后又去打印 D 的右边了~~
而当前我们只是处理了 D 的右边为 空才去打印 D 的情况
换句话说,有两种情况下可以打印 D:
1.D 的右边是 空
2.D 的右边被打印过了
因此我们需要记录它的右边是否被打印过了
先初始化 prev 为空
只要 top 被打印了,立马用 prev 指向它,标记已经打印过了
然后在 if 判断条件中,补充上 || top的右边==标记过的 prev
这样就能避免死循环了~~
Java代码:
java
/**
* Definition for a binary tree node.
* 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;
* }
* }
*/
class Solution {
//144. 二叉树的前序遍历
//解法一:递归
List<Integer> list=new ArrayList<>();
public List<Integer> preorderTraversal(TreeNode root) {
if(root==null) return list;
list.add(root.val);
preorderTraversal(root.left);
preorderTraversal(root.right);
return list;
}
}
java
/**
* Definition for a binary tree node.
* 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;
* }
* }
*/
class Solution {
//144. 二叉树的前序遍历
//解法二:栈
List<Integer> list=new ArrayList<>();
public List<Integer> preorderTraversal(TreeNode root) {
if(root==null) return list;
//栈的作用:暂存待处理右子树的父节点
Stack<TreeNode> stack=new Stack();
TreeNode cur=root;
//不加cur!=null一开始进不去
while(cur!=null||!stack.isEmpty()){
while(cur!=null){
//不空就入栈,暂存
stack.push(cur);
list.add(cur.val);
//接着前序遍历,往左走
cur=cur.left;
}
//左边空了,就把这个元素弹出来放进top里
TreeNode top=stack.pop();
//再去看这个元素的右边
cur=top.right;
}
return list;
}
}
java
/**
* Definition for a binary tree node.
* 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;
* }
* }
*/
class Solution {
//145. 二叉树的后序遍历
//解法一:递归
List<Integer> list=new ArrayList<>();
public List<Integer> postorderTraversal(TreeNode root) {
if(root==null) return list;
postorderTraversal(root.left);
postorderTraversal(root.right);
list.add(root.val);
return list;
}
}
java
/**
* Definition for a binary tree node.
* 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;
* }
* }
*/
class Solution {
//145. 二叉树的后序遍历
//解法二:栈
List<Integer> list=new ArrayList<>();
public List<Integer> postorderTraversal(TreeNode root) {
if(root==null) return list;
Stack<TreeNode> stack=new Stack();
TreeNode cur=root;
//用 prev 指向刚刚被打印过的点,防止死循环
TreeNode prev=null;
while(cur!=null||!stack.isEmpty()){
while(cur!=null){
stack.push(cur);
cur=cur.left;
}
//由于往左走之后要打印右边
//所以需要先peek()一下,获取到右边的节点
//因为弹出去之后,右边的就获取不到了,就丢了
TreeNode top=stack.peek();
if(top.right==null||top.right==prev){
list.add(top.val);
stack.pop();
prev=top;
}else{
cur=top.right;
}
}
return list;
}
}

