A.每日一题:144题+145题 二叉树的前序遍历+后序遍历

题目链接:

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;
    }
}
相关推荐
YuK.W29 分钟前
Leetcode100: 70.爬楼梯、118.杨辉三角、198.打家劫舍
java·算法·leetcode
这不小天嘛43 分钟前
JAVA八股——redis篇
java·开发语言·redis
众人皆醒我独醉2 小时前
Pod 一直 Terminating,死活删不掉?三个凶手,每一个你都意想不到
面试·kubernetes
旖-旎2 小时前
《LeetCode 64 最小路径和 || LeetCode 174 地下城游戏》
c++·算法·leetcode·动态规划
聚美智数3 小时前
黄历查询-运势查询-国际法定节假日查询-API接口介绍
android·java·数据库
凯瑟琳.奥古斯特3 小时前
力扣1009补码解法C++实现
开发语言·c++·算法·leetcode·职场和发展
Yeats_Liao5 小时前
18:JavaBean简介及其在表单处理与DAO设计模式中的应用-Java Web
java·后端·架构
范什么特西5 小时前
网络代理问题
java·linux·服务器
KaifuZeng5 小时前
通信与接口协议面试十、PCIe
单片机·嵌入式硬件·面试·通信与接口协议
三月不知肉味y5 小时前
2026-07-05-JAVA面试场景题训练
java·开发语言·面试