【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

相关文章

Python中的随机森林算法与实战

《Python中的随机森林算法与实战》本文详细介绍了随机森林算法,包括其原理、实现步骤、分类和回归案例,并讨论了其优点和缺点,通过面向对象编程实现了一个简单的随机森林模型,并应用于鸢尾花分类和波士顿房... 目录1、随机森林算法概述2、随机森林的原理3、实现步骤4、分类案例:使用随机森林预测鸢尾花品种4.1

Spring Security 从入门到进阶系列教程

Spring Security 入门系列 《保护 Web 应用的安全》 《Spring-Security-入门(一):登录与退出》 《Spring-Security-入门(二):基于数据库验证》 《Spring-Security-入门(三):密码加密》 《Spring-Security-入门(四):自定义-Filter》 《Spring-Security-入门(五):在 Sprin

哈希leetcode-1

目录 1前言 2.例题  2.1两数之和 2.2判断是否互为字符重排 2.3存在重复元素1 2.4存在重复元素2 2.5字母异位词分组 1前言 哈希表主要是适合于快速查找某个元素(O(1)) 当我们要频繁的查找某个元素,第一哈希表O(1),第二,二分O(log n) 一般可以分为语言自带的容器哈希和用数组模拟的简易哈希。 最简单的比如数组模拟字符存储,只要开26个c

不懂推荐算法也能设计推荐系统

本文以商业化应用推荐为例,告诉我们不懂推荐算法的产品,也能从产品侧出发, 设计出一款不错的推荐系统。 相信很多新手产品,看到算法二字,多是懵圈的。 什么排序算法、最短路径等都是相对传统的算法(注:传统是指科班出身的产品都会接触过)。但对于推荐算法,多数产品对着网上搜到的资源,都会无从下手。特别当某些推荐算法 和 “AI”扯上关系后,更是加大了理解的难度。 但,不了解推荐算法,就无法做推荐系

康拓展开(hash算法中会用到)

康拓展开是一个全排列到一个自然数的双射(也就是某个全排列与某个自然数一一对应) 公式: X=a[n]*(n-1)!+a[n-1]*(n-2)!+...+a[i]*(i-1)!+...+a[1]*0! 其中,a[i]为整数,并且0<=a[i]<i,1<=i<=n。(a[i]在不同应用中的含义不同); 典型应用: 计算当前排列在所有由小到大全排列中的顺序,也就是说求当前排列是第

csu 1446 Problem J Modified LCS (扩展欧几里得算法的简单应用)

这是一道扩展欧几里得算法的简单应用题,这题是在湖南多校训练赛中队友ac的一道题,在比赛之后请教了队友,然后自己把它a掉 这也是自己独自做扩展欧几里得算法的题目 题意:把题意转变下就变成了:求d1*x - d2*y = f2 - f1的解,很明显用exgcd来解 下面介绍一下exgcd的一些知识点:求ax + by = c的解 一、首先求ax + by = gcd(a,b)的解 这个

综合安防管理平台LntonAIServer视频监控汇聚抖动检测算法优势

LntonAIServer视频质量诊断功能中的抖动检测是一个专门针对视频稳定性进行分析的功能。抖动通常是指视频帧之间的不必要运动,这种运动可能是由于摄像机的移动、传输中的错误或编解码问题导致的。抖动检测对于确保视频内容的平滑性和观看体验至关重要。 优势 1. 提高图像质量 - 清晰度提升:减少抖动,提高图像的清晰度和细节表现力,使得监控画面更加真实可信。 - 细节增强:在低光条件下,抖

【数据结构】——原来排序算法搞懂这些就行,轻松拿捏

前言:快速排序的实现最重要的是找基准值,下面让我们来了解如何实现找基准值 基准值的注释:在快排的过程中,每一次我们要取一个元素作为枢纽值,以这个数字来将序列划分为两部分。 在此我们采用三数取中法,也就是取左端、中间、右端三个数,然后进行排序,将中间数作为枢纽值。 快速排序实现主框架: //快速排序 void QuickSort(int* arr, int left, int rig

poj 3974 and hdu 3068 最长回文串的O(n)解法(Manacher算法)

求一段字符串中的最长回文串。 因为数据量比较大,用原来的O(n^2)会爆。 小白上的O(n^2)解法代码:TLE啦~ #include<stdio.h>#include<string.h>const int Maxn = 1000000;char s[Maxn];int main(){char e[] = {"END"};while(scanf("%s", s) != EO

科研绘图系列:R语言扩展物种堆积图(Extended Stacked Barplot)

介绍 R语言的扩展物种堆积图是一种数据可视化工具,它不仅展示了物种的堆积结果,还整合了不同样本分组之间的差异性分析结果。这种图形表示方法能够直观地比较不同物种在各个分组中的显著性差异,为研究者提供了一种有效的数据解读方式。 加载R包 knitr::opts_chunk$set(warning = F, message = F)library(tidyverse)library(phyl