【LeetCode】二叉树的中序遍历(递归,迭代,Morris遍历)

news/2025/2/9 1:42:15/

目录

题目要求:给定一个二叉树的根节点 root ,返回 它的 中序 遍历 。

方法一:递归

方法二:迭代

思路分析:

复杂度分析

代码展示:

方法三:Morris 遍历

思路分析:

复杂度分析

代码展示:


题目要求:给定一个二叉树的根节点 root ,返回 它的 中序 遍历 。

示例 1:

输入:root = [1,null,2,3]
输出:[1,3,2]

提示:

  • 树中节点数目在范围 [0, 100] 内
  • -100 <= Node.val <= 100

 

方法一:递归

递归的方法二叉树的前序遍历在之前的博客中已经写过,需要的小伙伴可以点击链接查看

递归求二叉树的前中后序遍历

【LeetCode】二叉树的前序遍历(递归,迭代,Morris遍历)

这篇文章主要来讲解非递归的方法对二叉树进行中序遍历

方法二:迭代

思路分析:


迭代的方式其实与递归是等价的,区别在于递归的时候隐式地维护了一个栈,而我们在迭代的时候

需要显式地将这个栈模拟出来,其余的实现与细节都相同,具体可以参考下面的代码

复杂度分析

  • 时间复杂度:O(n),其中 n 是二叉树的节点数。每一个节点恰好被遍历一次。

  • 空间复杂度:O(n),为迭代过程中显式栈的开销,平均情况下为 O(log⁡n),最坏情况下树呈现链状,为 O(n)

代码展示:

 public List<Integer> inorderTraversal(TreeNode root) {List <Integer> list = new ArrayList<>();Stack <TreeNode> stack = new Stack<>();//栈非空或者root非空while(root != null || !stack.isEmpty()){//先根后左入栈while(root != null){stack.push(root);root = root.left;}//此时root为空,说明上一个入栈的root没有左子树//没有左子树,可以出栈root = stack.pop();list.add(root.val);//此时判断右子树root = root.right;}return list;}

方法三:Morris 遍历

Morris 遍历使用二叉树节点中大量指向 null 的指针,由 Joseph Morris 于 1979 年发明。

思路分析:

将当前根节点的左侧最右侧节点的right指向当前根节点,省去了栈的维护,连接之后可以直接顺着节点遍历完整个二叉树,以下图为例:

6f9c88bc38954a898dd01d66029bf510.jpeg

复杂度分析

  • 时间复杂度:O(n),其中 n 是二叉树的节点数。每一个节点恰好被遍历一次。

  • 空间复杂度:O(1)

代码展示:

    public List<Integer> inorderTraversal(TreeNode root) {List<Integer> list = new ArrayList<>();if(root == null){return list;}TreeNode cur1 = root;TreeNode cur2 = null;while(cur1 != null){cur2 = cur1.left;if(cur2 != null){while(cur2.right != null && cur2.right != cur1){cur2 = cur2.right;}//此时说明cur2走向了最右侧子树//1.还未连接,建立连接if(cur2.right != cur1){cur2.right = cur1;cur1 = cur1.left;continue;//否则说明已经走过,断开连接}else{cur2.right = null;list.add(cur1.val);}}else{list.add(cur1.val);}cur1 = cur1.right;}return list;}


http://www.ppmy.cn/news/35284.html

相关文章

STM32外设-定时器详解

0. 概述 本文针对STM32F1系列&#xff0c;主要讲解了其中的8个定时器的原理和功能 1. 定时器分类 STM32F1 系列中&#xff0c;除了互联型的产品&#xff0c;共有 8 个定时器&#xff0c;分为基本定时器&#xff0c;通用定时器和高级定时器基本定时器 TIM6 和 TIM7 是一个 16 位…

【linux】多线程控制详述

文章目录一、进程控制1.1 POSIX线程库1.2 创建线程pthread_create1.2.1 创建一批线程1.3 终止线程pthread_exit1.4 线程等待pthread_jion1.4.1 线程的返回值&#xff08;退出码&#xff09;1.5 取消线程pthread_cancel1.6 C多线程1.7 分离线程pthread_detach二、线程ID值三、线…

C语言——字符串函数(2)和内存函数

(一)strtok函数dilimiters参数是个字符串&#xff0c;定义了用作分隔符的字符集合第一个参数指定一个字符串&#xff0c;它包含了0个或者多个由dilimiters字符串中一个或者多个分隔符分割的标记。strtok函数找到str中的下一个标记&#xff0c;并将其用 \0 结尾&#xff0c;返回…

优秀程序员的5个特征,你在第几层?

每个人程序员都对未来的职业发展有着憧憬和规划&#xff0c;要做架构师、要做技术总监、要做CTO。但现实总是复杂的&#xff0c;日复一日的工作与生活总能让人一次又一次地陷入迷茫。大部分原因就是对职业发展轨迹和自我能力提升的一般规律缺乏认识&#xff0c;做事找不到方向或…

【多线程】创建线程有哪几种方式

目录1.继承Thread类2.实现Runnable接口3.实现Callable接口4.利用线程池1.继承Thread类 1.定义Thread类的子类&#xff0c;并重写该类的run()方法&#xff0c;该run()方法将作为线程执行体2.创建Thread子类的实例&#xff0c;即创建了线程对象3.调用线程对象的start()方法来启动…

eNSP 网络地址转换配置实验

关于本实验当使用私有IP地址的内部主机访问外网时&#xff0c;需要使用NAT将其私有IP地址转换为公有IP地址&#xff0c;此时需要在网关路由器上配置NAT来提供相应的地址转换服务。当网关路由器连接ISP的接口上未使用固定IP地址&#xff0c;而是动态地从ISP获取IP地址时&#xf…

Linux Debian11使用podman安装sqli-labs靶场环境

一、Sqli-labs简介 Sqli-labs是一个可以用来学习SQL注入的游戏教程&#xff0c;学习渗透可以借用这个工具来入门学习SQL注入的一些理论知识。 二、安装podman环境 Linux Debian11使用国内源安装Podman环境 三、podman安装sqli-labs靶场环境 1.podman搜索sqli-labs镜像 打…

大数加法【算法解析、代码模板、思路简单清晰】

791. 高精度加法 - AcWing题库 算法解析 大数加法其实本质上就是模拟 小学我们学的加法运算 分治 的思想 我们将一个很大的数字&#xff0c;拆成一个数的加法——分治思想 如何存储 如果对于一个真正很大的数字来说&#xff0c;可能long long都不支持&#xff08;最多支持19…