【leetcode系列】【算法】【中等】二叉树的中序遍历(递归,栈,莫里斯morris)

本文主要是介绍【leetcode系列】【算法】【中等】二叉树的中序遍历(递归,栈,莫里斯morris),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

目录

 

题目:

解题思路:

方法一:递归(时间O(N),空间O(N))

方法二:栈(时间O(N),空间O(N))

方法三:莫里斯遍历(时间O(N),空间O(1))

解题思路:

方法一:递归

方法二:栈

方法三:莫里斯


题目:

题目链接: https://leetcode-cn.com/problems/binary-tree-inorder-traversal/

 

解题思路:

方法一:递归(时间O(N),空间O(N))

每次递归,如果有左子树,就继续使用左子树继续递归

如果没有左子树,就将当前值加入到结果集中,返回到上一层递归中

在上一层递归中,先将当前值加入到结果集中,继续判断是否有右子树

如果有右子树,继续使用右子树递归,如果没有右子树,继续返回上一层递归,重复此逻辑

 

方法二:栈(时间O(N),空间O(N))

先将根节点入栈,开始遍历

只要栈不为空,就从栈中获取栈顶的元素,并判断是否有左子树

如果有左子树,将左子树入栈,然后继续遍历;下次遍历获取到的栈顶元素,为本次遍历入栈的左子树

如果没没有左子树,将当前值加入到结果集中,并将栈顶子树出栈

继续从栈顶获取子树,并将栈顶子树出栈,将值加入到结果集中,然后判断是否有右子树

如果有右子树,则将右子树出栈,继续大循环;如果没有右子树,则继续小循环,获取栈顶元素

图示如下:

将根节点入栈

将1的左子树2入栈

将2的左子树4入栈

因为4没有左子树,将4出栈,并将4加入到结果集res中

因为4没有右子树,所以继续将栈顶元素2出栈,并加入到结果集res中

因为2有右子树,所以不继续从栈顶获取元素,而将2的右子树5入栈

5的情况与4相同,将5出栈,加入到结果集中

从栈顶将1出栈,加入到结果集中

因为1有右子树,所以将1的右子树3入栈

因为3没有左子树,将栈顶元素3出栈,加入到结果集

将3的右子树入栈

将6出栈,加入到结果集中

栈中没有元素,停止遍历,返回结果

 

方法三:莫里斯遍历(时间O(N),空间O(1))

逻辑大致如下:

变量:

  1. root:树的根节点
  2. curr:当前遍历到的节点,初始化为root
  3. prev:辅助节点,初始化为空

流程:

  1. 如果curr左子树为空,则将curr值加入到结果集中,并开始遍历curr的右子树
  2. 如果curr左子树不为空,则进行下记操作:
    1. prev从curr左子树的右子树开始遍历,直到没有右子树,或者遍历到curr节点
    2. 如果prev右子树为空,则将prev右子树指向curr
    3. 如果prev右子树不为空,则将curr.val加入到结果集,更新curr = curr.right右子树,prev = None,继续遍历

图示:

假设一个树原始结构如下:

黑色节点永远为原始root节点,此时将curr指向root节点,curr节点左子树为2,不为空,此时将prev指向2,开始从2的右子树5遍历:

当搜索到8时,因为8没有右子树,停止搜索,此时三个节点情况如下(curr、root都在1位置):

此时,将prev的右子树指向curr,更新curr = curr.left,此时的节点位置和连接情况如下(实线为原始树结构,虚线为新加的连接):

继续循环,此时prev = 2的左子树不为空,继续将prev指向curr的左子树,开始搜索:

4没有右子树,所以直接退出搜索,继续将prev的右子树指向curr,更新curr = curr.left,此时节点位置和链接情况如下(因为prev指向4后,没有向右子树遍历,所以此时prev和curr在同一位置):

此时继续遍历时,发现curr没有左子树,所以将curr的值加入到结果集res中,通过虚线,更新curr = curr.right,开始下次循环。此时curr = 2,所以prev = curr.left继续从2的左子树4开始搜索,4的右节点为2,符合了curr = prev的条件,搜索停止,此时情况如下:

搜索停止时,prev = 4的右子树不为空,所以此时将2加入到结果集中,更新curr = curr.right,删除掉之前多添加出来的连接,即更新prev.right = None,继续循环:

之后逻辑与上述相同,图示流程如下:

 

解题思路:

方法一:递归

# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, x):
#         self.val = x
#         self.left = None
#         self.right = Noneclass Solution:def inorderTraversal(self, root: TreeNode) -> List[int]:def order_help(node, res):if node and node.left:order_help(node.left, res)if node:res.append(node.val)if node and node.right:order_help(node.right, res)res = []order_help(root, res)return res

 

方法二:栈

# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, x):
#         self.val = x
#         self.left = None
#         self.right = Noneclass Solution:def inorderTraversal(self, root: TreeNode) -> List[int]:if not root:return []node_stack = [root]res = []while 0 < len(node_stack):if node_stack[-1].left:node_stack.append(node_stack[-1].left)continuewhile 0 < len(node_stack):last_node = node_stack[-1]node_stack.pop()res.append(last_node.val)if last_node.right:node_stack.append(last_node.right)breakreturn res

 

方法三:莫里斯

# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, x):
#         self.val = x
#         self.left = None
#         self.right = Noneclass Solution:def inorderTraversal(self, root: TreeNode) -> List[int]:curr = rootprev = Noneres = []while curr:if not curr.left:res.append(curr.val)curr = curr.rightelse:prev = curr.leftwhile prev.right and prev.right != curr:prev = prev.rightif not prev.right:prev.right = currcurr = curr.leftelse:res.append(curr.val)prev.right = Nonecurr = curr.rightreturn res

 

这篇关于【leetcode系列】【算法】【中等】二叉树的中序遍历(递归,栈,莫里斯morris)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/633146

相关文章

Java中的雪花算法Snowflake解析与实践技巧

《Java中的雪花算法Snowflake解析与实践技巧》本文解析了雪花算法的原理、Java实现及生产实践,涵盖ID结构、位运算技巧、时钟回拨处理、WorkerId分配等关键点,并探讨了百度UidGen... 目录一、雪花算法核心原理1.1 算法起源1.2 ID结构详解1.3 核心特性二、Java实现解析2.

MySQL存储过程之循环遍历查询的结果集详解

《MySQL存储过程之循环遍历查询的结果集详解》:本文主要介绍MySQL存储过程之循环遍历查询的结果集,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录前言1. 表结构2. 存储过程3. 关于存储过程的SQL补充总结前言近来碰到这样一个问题:在生产上导入的数据发现

python进行while遍历的常见错误解析

《python进行while遍历的常见错误解析》在Python中选择合适的遍历方式需要综合考虑可读性、性能和具体需求,本文就来和大家讲解一下python中while遍历常见错误以及所有遍历方法的优缺点... 目录一、超出数组范围问题分析错误复现解决方法关键区别二、continue使用问题分析正确写法关键点三

使用雪花算法产生id导致前端精度缺失问题解决方案

《使用雪花算法产生id导致前端精度缺失问题解决方案》雪花算法由Twitter提出,设计目的是生成唯一的、递增的ID,下面:本文主要介绍使用雪花算法产生id导致前端精度缺失问题的解决方案,文中通过代... 目录一、问题根源二、解决方案1. 全局配置Jackson序列化规则2. 实体类必须使用Long封装类3.

mysql递归查询语法WITH RECURSIVE的使用

《mysql递归查询语法WITHRECURSIVE的使用》本文主要介绍了mysql递归查询语法WITHRECURSIVE的使用,WITHRECURSIVE用于执行递归查询,特别适合处理层级结构或递归... 目录基本语法结构:关键部分解析:递归查询的工作流程:示例:员工与经理的层级关系解释:示例:树形结构的数

Springboot实现推荐系统的协同过滤算法

《Springboot实现推荐系统的协同过滤算法》协同过滤算法是一种在推荐系统中广泛使用的算法,用于预测用户对物品(如商品、电影、音乐等)的偏好,从而实现个性化推荐,下面给大家介绍Springboot... 目录前言基本原理 算法分类 计算方法应用场景 代码实现 前言协同过滤算法(Collaborativ

Java遍历HashMap的6种常见方式

《Java遍历HashMap的6种常见方式》这篇文章主要给大家介绍了关于Java遍历HashMap的6种常见方式,方法包括使用keySet()、entrySet()、forEach()、迭代器以及分别... 目录1,使用 keySet() 遍历键,再通过键获取值2,使用 entrySet() 遍历键值对3,

openCV中KNN算法的实现

《openCV中KNN算法的实现》KNN算法是一种简单且常用的分类算法,本文主要介绍了openCV中KNN算法的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的... 目录KNN算法流程使用OpenCV实现KNNOpenCV 是一个开源的跨平台计算机视觉库,它提供了各

C语言函数递归实际应用举例详解

《C语言函数递归实际应用举例详解》程序调用自身的编程技巧称为递归,递归做为一种算法在程序设计语言中广泛应用,:本文主要介绍C语言函数递归实际应用举例的相关资料,文中通过代码介绍的非常详细,需要的朋... 目录前言一、递归的概念与思想二、递归的限制条件 三、递归的实际应用举例(一)求 n 的阶乘(二)顺序打印

springboot+dubbo实现时间轮算法

《springboot+dubbo实现时间轮算法》时间轮是一种高效利用线程资源进行批量化调度的算法,本文主要介绍了springboot+dubbo实现时间轮算法,文中通过示例代码介绍的非常详细,对大家... 目录前言一、参数说明二、具体实现1、HashedwheelTimer2、createWheel3、n