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;
    }
}
相关推荐
All for pursuit.4 小时前
【二叉树-10】114.二叉树展开为链表
数据结构·c++·算法·leetcode·链表
怕浪猫4 小时前
分享一个做视频的skill,这条白板视频,每一笔都是代码画的
前端·javascript·面试
FYKJ_20105 小时前
springboot助农产品销售商城05829-计算机课程设计、毕业设计
java·spring boot·python·mysql·spark·django
弈栈录6 小时前
基于 Spring Boot 构建生产级 AI 应用平台
后端·面试·架构
user_admin_god7 小时前
第 10 篇:拼上下文与生成——预算、边界与防幻觉
java·人工智能·spring boot·语言模型
用户3126874877207 小时前
GC 算法与垃圾收集器演进:从 Serial 到 ZGC
java
天天被压力8 小时前
【别再到处找免费股票数据API了:官方204个接口,32篇一次讲透 #02】涨停跌停与特色股池:5类股池接口一次拉全
java·人工智能·python
斯维赤8 小时前
从 @Tool 到 Agent 流水线:LangChain4j 进阶教学,一个库打全套
java·后端
SimonKing8 小时前
SSE项目`nexus-sse`持续优化,不一样的视觉效果
java·后端·程序员
斑鸠喳喳8 小时前
读写锁模式 Read-Write Lock
java·后端