【LeetCode热题100】打卡第27天:二叉树的前序、中序、后序遍历

news2024/11/15 17:18:23

文章目录

  • 【LeetCode热题100】打卡第27天:二叉树的前序、中序、后序遍历
    • ⛅前言
    • 📕二叉树的前序遍历
      • 🔒题目
      • 🔑题解
    • 📕二叉树的中序遍历
      • 🔒题目
      • 🔑题解
    • 📕二叉树的后序遍历
      • 🔒题目
      • 🔑题解
    • 二叉树遍历——迭代统一写法

【LeetCode热题100】打卡第27天:二叉树的前序、中序、后序遍历

⛅前言

大家好,我是知识汲取者,欢迎来到我的LeetCode热题100刷题专栏!

精选 100 道力扣(LeetCode)上最热门的题目,适合初识算法与数据结构的新手和想要在短时间内高效提升的人,熟练掌握这 100 道题,你就已经具备了在代码世界通行的基本能力。在此专栏中,我们将会涵盖各种类型的算法题目,包括但不限于数组、链表、树、字典树、图、排序、搜索、动态规划等等,并会提供详细的解题思路以及Java代码实现。如果你也想刷题,不断提升自己,就请加入我们吧!QQ群号:827302436。我们共同监督打卡,一起学习,一起进步。

LeetCode热题100专栏🚀:LeetCode热题100

Gitee地址📁:知识汲取者 (aghp) - Gitee.com

题目来源📢:LeetCode 热题 100 - 学习计划 - 力扣(LeetCode)全球极客挚爱的技术成长平台

PS:作者水平有限,如有错误或描述不当的地方,恳请及时告诉作者,作者将不胜感激

📕二叉树的前序遍历

中左右

🔒题目

原题链接:144.二叉树的前序遍历

image-20230623152715066

🔑题解

  • 解法一:递归实现

    在使用DFS时,也经常这么用O(∩_∩)O

    public class Solution {
        public List<Integer> preorderTraversal(TreeNode root) {
            List<Integer> ans = new ArrayList<>();
            traversalTree(ans, root);
            return ans;
        }
    
        private void traversalTree(List<Integer> ans, TreeNode root) {
            if (root==null){
                return;
            }
            ans.add(root.val);
            traversalTree(ans, root.left);
            traversalTree(ans, root.right);
        }
    }
    

    复杂度分析:

    • 时间复杂度: O ( n ) O(n) O(n)
    • 空间复杂度: O ( n ) O(n) O(n)

    其中 n n n 为数组中元素的个数

  • 解法二:迭代实现

    这个理解起来也不难,本质上和解法一是一样的。就是使用栈模拟递归的过程,区别是递归过程中是隐士的维护一个栈,而这里是显示维护一个栈。不是很理解的话,可以画个草图

    image-20230623160721709

    public class Solution {
        public List<Integer> preorderTraversal(TreeNode root) {
            List<Integer> ans = new ArrayList<>();
            Deque<TreeNode> stack = new ArrayDeque<>();
            TreeNode cur = root;
            while (!stack.isEmpty() || cur != null){
                // 第一遍循环,把根节点左子树所有根节点入栈
                // 后面再入栈右节点
                while (cur != null){
                    ans.add(cur.val);
                    stack.push(cur);
                    cur = cur.left;
                }
                // 自底向上出栈
                TreeNode node = stack.pop();
                if (node.right != null){
                    cur = node.right;
                }
            }
            return ans;
        }
    }
    

    复杂度分析:

    • 时间复杂度: O ( n ) O(n) O(n)
    • 空间复杂度: O ( n ) O(n) O(n)

    其中 n n n 为数组中元素的个数

📕二叉树的中序遍历

左中右

🔒题目

原题链接:94.二叉树的中序遍历

image-20230623152800131

🔑题解

  • 解法一:递归实现

    public class Solution {
        public List<Integer> inorderTraversal(TreeNode root) {
            List<Integer> ans = new ArrayList<>();
            traversal(ans, root);
            return ans;
        }
    
        private void traversal(List<Integer> ans, TreeNode root) {
            if (root == null){
                return;
            }
            traversal(ans, root.left);
            ans.add(root.val);
            traversal(ans, root.right);
        }
    }
    
  • 解法二:迭代实现

    public class Solution {
        public List<Integer> inorderTraversal(TreeNode root) {
            List<Integer> ans = new ArrayList<>();
            Deque<TreeNode> stack = new ArrayDeque<>();
            TreeNode cur = root;
            while (!stack.isEmpty() || cur != null) {
                while (cur != null) {
                    stack.push(cur);
                    cur = cur.left;
                }
                TreeNode node = stack.pop();
                ans.add(node.val);
                if (node != null){
                    cur = node.right;
                }
            }
            return ans;
        }
    }
    

📕二叉树的后序遍历

左右中

🔒题目

原题链接:145.二叉树的后序遍历

image-20230623152904635

🔑题解

  • 解法一:递归实现

    public class Solution {
        public List<Integer> postorderTraversal(TreeNode root) {
            List<Integer> ans = new ArrayList<>();
            traversal(ans, root);
            return ans;
        }
    
        private void traversal(List<Integer> ans, TreeNode root) {
            if (root == null){
                return;
            }
            traversal(ans, root.left);
            traversal(ans, root.right);
            ans.add(root.val);
        }
    }
    
  • 解法二:迭代实现

    感觉这个是三个当中最难的想了好久😫,难点在于要防止死循环

    PS:有可能是今天题目写的有点多了,头有点晕了🤣

    public class Solution {
        public List<Integer> postorderTraversal(TreeNode root) {
            List<Integer> ans = new ArrayList<>();
            Deque<TreeNode> stack = new ArrayDeque<>();
            TreeNode cur = root;
            TreeNode pre = null;
            while (!stack.isEmpty() || cur != null) {
                while (cur != null) {
                    stack.push(cur);
                    cur = cur.left;
                }
                // 自底向上出栈
                cur = stack.pop();
                if (cur.right == null || cur.right == pre) {
                    // 右节点为空 或 右节点已遍历
                    ans.add(cur.val);
                    pre = cur;
                    cur = null;
                }else {
                    // 左子树遍历完,右节点不为空,右节点要先输出
                    // 将当前根节点加入,因为当前根节点要在右节点之后输出
                    stack.push(cur);
                    // 将当前指针改成右节点,用于遍历右子树
                    cur = cur.right;
                }
            }
            return ans;
        }
    }
    

二叉树遍历——迭代统一写法

参考:「代码随想录」帮你对二叉树不再迷茫,彻底吃透前中后序递归法(递归三部曲)和迭代法(不统一写法与统一写法) - 二叉树的后序遍历 - 力扣(LeetCode)

注意:统一写法的栈不能使用ArrayDeque,因为ArrayDeque的add方法如果添加null元素会直接爆NPE

这种统一写法的好处,再与你只要是熟悉一种写法,其它写法信手拈来,但是效率没有前面的高(经过提交测试),但有一说一我还是喜欢前面的写法,不太喜欢这种统一的写法

/**
 * @author ghp
 * @title 前序遍历
 */
class Solution {

    public List<Integer> preorderTraversal(TreeNode root) {
        List<Integer> ans = new ArrayList<>();
        Stack<TreeNode> stack = new Stack<>();
        if (root != null) stack.push(root);
        while (!stack.isEmpty()) {
            TreeNode node = stack.pop();
            if (node != null) {
                if (node.right != null) stack.push(node.right);
                if (node.left != null) stack.push(node.left);
                stack.push(node);
                stack.push(null);

            } else {
                node = stack.peek();
                stack.pop();
                ans.add(node.val);
            }
        }
        return ans;
    }
}
class Solution {

    public List<Integer> preorderTraversal(TreeNode root) {
        List<Integer> ans = new ArrayList<>();
        Stack<TreeNode> stack = new Stack<>();
        if (root != null) stack.push(root);
        while (!stack.isEmpty()) {
            TreeNode node = stack.pop();
            if (node != null) {
                if (node.right != null) stack.push(node.right);
                stack.push(node);
                stack.push(null);
                if (node.left != null) stack.push(node.left);
            } else {
                node = stack.peek();
                stack.pop();
                ans.add(node.val);
            }
        }
        return ans;
    }
}
class Solution {

    public List<Integer> preorderTraversal(TreeNode root) {
        List<Integer> ans = new ArrayList<>();
        Stack<TreeNode> stack = new Stack<>();
        if (root != null) stack.push(root);
        while (!stack.isEmpty()) {
            TreeNode node = stack.pop();
            if (node != null) {
                stack.push(node);
                stack.push(null);
                if (node.right != null) stack.push(node.right);
                if (node.left != null) stack.push(node.left);
            } else {
                node = stack.peek();
                stack.pop();
                ans.add(node.val);
            }
        }
        return ans;
    }
}

中序+前序 ===> 后序(能推导出完整的二叉树)

中序+后序 ===> 前序(能推导出完整的二叉树)

前序+后序 =\=> 中序(不能推导出完整的二叉树)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/677363.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

(万字长文)React 18 源码与原理解读 —— 看这一篇就够了

写在专栏开头&#xff08;叠甲&#xff09; 作者并不是前端技术专家&#xff0c;也只是一名喜欢学习新东西的前端技术小白&#xff0c;想要学习源码只是为了应付急转直下的前端行情和找工作的需要&#xff0c;这篇专栏是作者学习的过程中自己的思考和体会&#xff0c;也有很多参…

django中模板的使用

django中模板的使用 第一步 创建模板文件夹第二步 把模板存放进去第三步 把模板路径 加入到setting.py第四步 在视图函数处理第五步 路由挂载第六步 网页访问 第一步 创建模板文件夹 在项目的同层级下 新建模板文件夹 第二步 把模板存放进去 index.html <!DOCTYPE html&…

【Docker】一文了解Docker

文章目录 什么是Docker?为什么要使用Docker&#xff1f;与虚拟机的比较Docker架构Docker使用场景Docker安装阿里云镜像加速器1、登录阿里云2、找到镜像加速器3、配置使用 如今Docker的使用已经非常普遍&#xff0c;特别在一线互联网公司。使用Docker技术可以帮助企业快速水平扩…

C++ 自己动手实现简单的文件操作 (2023.6.23)

C 自己动手实现简单的文件操作 2023.6.23 引言1、文件简介2、各式各样的文件格式2.1 不同类型文件的扩展名2.1.1 文本文件2.1.2 数据文件2.1.3 音频文件2.1.4 视频文件2.1.5 电子书文件2.1.6 3D图像文件2.1.7 位图文件2.1.8 矢量图文件2.1.9 相机原始文件2.1.10 页面布局文件2.…

自监督对比学习框架SimCLR原理

目录 一、前言 人工智能发展近况 对比学习 二、数据集介绍 STL-10数据集 三、无监督图像表征对比学习 SimCLR SimCLR算法基本原理 数据增强与正负样本匹配 编码器 损失函数 对比学习全过程 四、有监督的图像下游任务迁移 替换下游任务网络层 有监督训练 五、实…

环境配置 | Git的安装及配置[图文详情]

Git是一个开源的分布式版本控制系统&#xff0c;可以有效、高速地处理从小到大的项目版本管理。下面介绍了基础概念及详细的用图文形式介绍一下git安装过程. 目录 1.Git基础概念 2.Git的下载及安装 3.常见的git命令 Git高级技巧 Git与团队协作 1.Git基础概念 仓库&#…

Charm-Crypto在Anaconda虚拟环境下的安装教程--基于Ubuntu20.04

第零步 VMware虚拟机设置和安装Anaconda虚拟环境 因为后面要编译源码&#xff0c;所以最好把CPU设置为最大&#xff0c;例如我的电脑是4核8线程&#xff0c;则&#xff1a; 关于Anaconda虚拟环境&#xff0c;这里不再赘述&#xff0c;后面都假设已经安装好虚拟环境&#xff0c;…

包装类--Math 类--Arrays 类--System 类

包装类–Math 类–Arrays 类–System 类 包装类 包装类的分类 包装类和基本数据的转换 演示包装类和基本数据类型的相互转换&#xff0c;这里以int和Integer演示。 1&#xff09;jdk5前的手动装箱和拆箱方式&#xff0c;装箱&#xff1a;基本类型&#xff0d;>包装类型&…

OpenAI收费标准,ChatGPT调用须知!

OpenAI收费标准&#xff0c;ChatGPT调用须知&#xff01; 免费镜像站价格说明GPT4GPT3.5图片模型如何付费 免费镜像站 ChatGPT有很多镜像站&#xff0c;需要输入API-KEY才可以使用&#xff0c;镜像站不会进行收费&#xff0c;而是OpenAI会对您进行收费。本文主要说明OpenAI的收…

【好书精读】网络是怎样连接的 —— IP 与以太网的包收发操作

&#xff08; 该图由AI制作 &#xff09; 目录 包的基本知识 包收发操作概览 生成包含接收方 IP 地址的 IP 头部 生成以太网用的 MAC 头部 通过 ARP 查询目标路由器的 MAC 地址 以太网的基本知识 将 IP 包转换成电或光信号发送出去 给网络包再加 3 个控制数据 向集线…

代码随想录算法训练营第四十一天 | 背包问题(一维、二维)、416. 分割等和子集

01背包&#xff1a;n种物品&#xff0c;每种物品只有1个&#xff0c;有相应的重量和价值 最多只能装m的重量&#xff0c;最多价值为多少&#xff1f; dp[i][j] : [0, i]物品任取放进容量为j的背包里 不放物品i&#xff1a;dp[i-1][j] 放物品i&#xff1a;dp[i-1][j-weight[…

如何系统性的学习Python语言

零基础同学的福音来了&#xff0c;如果你对Python语言的学习感兴趣&#xff0c;接下来可以由浅入深的了解下Python语言&#xff0c;哪怕你是零基础的小白也完全可以学会的&#xff0c;最后也会给大家放出学习和实例相结合的教程及方法&#xff0c;给到各位同学系统性的教学&…

ES-索引管理

前言 数据类型 ​ 搜索引擎是对数据的检索&#xff0c;所以我们先从生活中的数据说起。我们生活中的数据总体分为两种&#xff1a; 结构化数据非结构化数据 结构化数据&#xff1a; 也称作行数据&#xff0c;是由二维表结构来逻辑表达和实现的数据&#xff0c;严格地遵循数…

<C语言> 数组

1.一维数组的创建和初始化。 1.1 数组的创建 数组是一组相同类型元素的集合。 使用以下方式声明一个一维数组&#xff1a; type arrayName[arraySize];type是数组中元素的类型&#xff0c;arrayName是数组的名称&#xff0c;arraySize是数组的大小&#xff08;即元素的个数&a…

linux系统中如何制作rootfs?详细教程

如何制作rootfs&#xff1f;安排&#xff01;想直奔主题的&#xff0c;直接跳到第四部分。 一、分析 1. 文件系统简介 理论上说一个嵌入式设备如果内核能够运行起来&#xff0c;且不需要运行用户进程的话&#xff0c;是不需要文件系统的&#xff0c;文件系统简单的说就是一种…

硬件入门之什么是mos管

硬件入门之什么是mos管 文章目录 硬件入门之什么是mos管一、mos管是什么&#xff1f;MOS管常用于&#xff1a; 驱动大功率电路中。MOS选型参数mos管调参数 二、实际应用场景1.防反接保护电路&#xff09;2.防过压保护电路3.防反接防过压电路一体电路4.驱动电路 总结 一、mos管是…

VS+QT+VTK三维网格显示-点面选择-法线法向量显示-配准-分割窗体程序

程序示例精选 VSQTVTK三维网格显示-点面选择-法线法向量显示-配准-分割窗体程序 如需安装运行环境或远程调试&#xff0c;见文章底部个人QQ名片&#xff0c;由专业技术人员远程协助&#xff01; 前言 这篇博客针对<<VSQTVTK三维网格显示-点面选择-法线法向量显示-配准-分…

Quartz使用H2数据库(嵌入模式)进行持久化

使用H2(嵌入模式)持久化Quartz任务 &#x1f51d;前言&#xff1a; Quartz在包内提供了多种数据库的sql文件&#xff0c;大家可以选择方便的使用。路径如下。 1.初始化h2(不使用Server模式) public class InitH2 {private static String USER_NAME "lee";private…

Unity简单操作:InputSystem获取WASD键盘输入 移动人物

目录 安装InputSystem 在编辑的脚本中使用 InputSystem生成的脚本 Unity版本&#xff1a;2019.2.3f1 安装InputSystem 菜单栏/Window/Package Manager/Input System 工程面板内 右键-->创建Input Actions 选中New Controls改名为PlayerControls 然后属性 面板按下Edit as…

软件项目管理 第七章 软件项目的质量管理与配置管理 课后习题参考答案——主编:李冰、张桥珍、刘玉娥

第七章 软件项目的质量管理与配置管理 课后习题参考答案 1.选择题 (1)项目质量管理的最终责任由谁来承担?&#xff08;D&#xff09; A.项目开发人员 B.采购经理 C.质量经理 D.项目经理 (2)“质量成本”是一个项目管理概念,它说明了下列哪项成本?…