☰
LeetCode 0094 二叉树的中序遍历:递归与显式栈迭代双解法详解(AlgoNote 算法通关手册)
2026/9/28 7:12:59 网站建设 项目流程
  • 教程
  • 文档
  • 知识库

【免费下载链接】AlgoNote

⛽️「算法通关手册」:从零开始的「算法与数据结构」学习教程,200 道「算法面试热门题目」,1000+ 道「LeetCode 题目解析」,持续更新中!

项目地址:https://gitcode.com/gh_mirrors/le/AlgoNote
点击查看免费下载

本篇技术指南围绕「算法通关手册」AlgoNote 仓库中的经典题解 0094. 二叉树的中序遍历 展开,系统讲解二叉树中序遍历的「左子树 → 根节点 → 右子树」访问规则,并给出递归与显式栈迭代两种完整可运行的 Python 实现。读完本文,你将掌握中序遍历的递归模板、非递归模拟系统栈的关键技巧,理解其在二叉搜索树(BST)有序序列生成、求第 K 小元素等高频场景中的应用,并能与同仓库的前序、后序遍历解法横向对比。

1. 题目理解:LeetCode 0094 要求什么

1.1 题目大意

给定一个二叉树的根节点root,要求返回该二叉树的中序遍历结果。

中序遍历遵循「左子树 → 根节点 → 右子树」的访问顺序:先递归遍历左子树,再访问当前根节点,最后递归遍历右子树。只要严格遵循这一顺序,无论子树多深,最终输出的节点值序列都是中序序列。

1.2 数据范围与约束

约束项取值范围
树中节点数目$[0, 100]$(可以为空树)
节点值Node.val$[-100, 100]$

空树(root = [])属于合法输入,返回值应为空列表[]。

1.3 示例

示例 1:

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

该树结构为:根节点1,右子树根节点2,2的左孩子为3。按中序顺序遍历得到1 → 3 → 2。

示例 2:

输入:root = [] 输出:[]

2. 解题思路 1:递归遍历

2.1 算法思想

二叉树本身具有递归结构(根节点 + 左子树 + 右子树),因此中序遍历可以自然地用递归实现。递归实现步骤为:

  1. 判断二叉树是否为空,为空则直接返回(递归终止条件)。
  2. 先递归遍历左子树。
  3. 然后访问根节点(将root.val加入结果列表)。
  4. 最后递归遍历右子树。

关键在于"访问根节点"这一操作的位置:它被放在左子树递归调用之后、右子树递归调用之前,这正是中序遍历区别于前序(根在最前)与后序(根在最后)的本质所在。

2.2 代码实现

class Solution: def inorderTraversal(self, root: TreeNode) -> List[int]: res = [] def inorder(root): if not root: return inorder(root.left) # 1. 递归遍历左子树 res.append(root.val) # 2. 访问根节点 inorder(root.right) # 3. 递归遍历右子树 inorder(root) return res

这段代码与仓库中 二叉树的遍历教程 的中序遍历递归实现(3.1 节)结构一致:内部嵌套函数inorder负责递归,res列表闭包共享,实现最简、最不易出错,是面试中最推荐的写法。

2.3 复杂度分析

  • 时间复杂度:$O(n)$。每个节点恰好被访问一次,其中 $n$ 是二叉树的节点数目。
  • 空间复杂度:$O(n)$。递归调用栈的深度等于树的高度 $h$,最坏情况下树退化为单链表,栈深度为 $O(n)$;结果数组同样占用 $O(n)$ 空间。

3. 解题思路 2:显式栈迭代遍历

3.1 算法思想

递归实现依赖系统调用栈,我们也可以使用一个显式栈stack手动模拟整个递归过程,从而避免递归深度过大带来的栈溢出风险。

核心难点:与前序遍历不同,中序遍历要求"访问根节点"必须发生在左子树全部遍历完之后。因此必须保证——在左子树访问完成之前,当前节点不能提前出栈。

具体做法:

  1. 判断二叉树是否为空,为空则直接返回。
  2. 初始化一个空栈stack。
  3. 当根节点或栈不为空时循环执行:
    • 若当前节点不为空:循环遍历左子树,不断将当前子树的根节点入栈,直到到达最左侧节点;
    • 若当前节点为空:说明已无左子树,此时弹出栈顶元素node并访问它,然后转向node的右子树,重复上述循环。

这个流程保证:节点在左子树完全入栈之后才出栈并被访问,输出严格符合「左 → 根 → 右」的中序顺序。仓库教程 二叉树的遍历教程 的 3.2 节使用了独立的cur指针变量承载"当前节点",语义上更清晰,而本题解直接用root变量复用指针,逻辑完全等价。

3.2 代码实现

class Solution: def inorderTraversal(self, root: Optional[TreeNode]) -> List[int]: if not root: # 二叉树为空直接返回 return [] res = [] stack = [] while root or stack: # 根节点或栈不为空 while root: stack.append(root) # 将当前树的根节点入栈 root = root.left # 找到最左侧节点 node = stack.pop() # 遍历到最左侧,当前节点无左子树时,将最左侧节点弹出 res.append(node.val) # 访问该节点 root = node.right # 尝试访问该节点的右子树 return res

3.3 复杂度分析

  • 时间复杂度:$O(n)$。每个节点入栈一次、出栈一次,总操作次数与节点数 $n$ 线性相关。
  • 空间复杂度:$O(n)$。栈中最多同时存放树的高度 $h$ 个节点,最坏情况(链状树)为 $O(n)$。

4. 两种思路对比与选型建议

对比维度递归实现显式栈迭代实现
代码量极短,结构直观稍长,需理解入栈/出栈时机
依赖依赖系统调用栈手动维护显式栈
栈溢出风险树深较大时存在可规避,由显式栈控制
时空复杂度均为 $O(n)$均为 $O(n)$
适用场景面试快速作答、逻辑演示生产环境大深度树、工程化要求

两者的时间与空间复杂度完全一致。选型建议:笔试/面试优先写递归,代码简洁不易出错;若题目明确要求非递归,或树深度可能超过递归栈限制(如 $10^4$ 量级节点且呈链状),则应采用显式栈迭代写法。

5. 中序遍历的经典应用:二叉搜索树有序序列

中序遍历最有价值的应用场景是二叉搜索树(BST)。根据 BST 性质——左子树所有节点值 < 根节点值 < 右子树所有节点值(详见仓库 二叉搜索树基础教程),对 BST 做中序遍历得到的节点值序列必然是严格递增的。

这一性质衍生出大量高频题目,例如仓库中的经典题解 0230. 二叉搜索树中第 K 小的元素 就采用了中序遍历方案:

class Solution: def kthSmallest(self, root: Optional[TreeNode], k: int) -> int: self.count = 0 # 计数器,记录当前访问的节点序号 self.result = 0 # 存储结果 def inorder_traversal(node): if not node: return inorder_traversal(node.left) # 遍历左子树 self.count += 1 # 访问根节点,计数 +1 if self.count == k: self.result = node.val return inorder_traversal(node.right) # 遍历右子树 inorder_traversal(root) return self.result

该解法的时间复杂度为 $O(k)$(找到第 $k$ 个节点即提前返回,无需遍历完整棵树),空间复杂度为 $O(h)$($h$ 为树高)。这正是中序遍历在"按序处理节点"场景下的典型应用,说明掌握本题的遍历模板可以直接迁移到更多进阶题目。

6. 与前后序遍历的横向对比

将本题解与仓库中的 0144. 二叉树的前序遍历题解 对照阅读,可以清晰看到三种深度优先遍历的异同:

遍历方式访问顺序递归实现关键差异非递归实现关键差异
前序遍历根 → 左 → 右先res.append再递归根先入栈,右子树先入栈、左子树后入栈(保证左先弹出)
中序遍历(本题)左 → 根 → 右递归左子树后再res.append一路向左入栈,无左子树时弹出并访问,再转向右子树
后序遍历左 → 右 → 根左右子树递归完后再res.append需额外标记右子树访问状态(如prev指针)

三种遍历的递归与迭代时间复杂度均为 $O(n)$;非递归实现中,中序的关键约束是"左子树访问前当前节点不能提前出栈",这是与前序(出栈即访问)最本质的区别。

7. 仓库延伸阅读

本专题在 AlgoNote 仓库中有着完整的知识链路,建议按以下顺序深入学习:

  • 二叉树的中序遍历题解(本文主体):递归与显式栈双解法原文;
  • 二叉树的遍历教程:前序、中序、后序、层序四种遍历的系统讲解与对比总结表;
  • 二叉树的前序遍历题解:对照阅读,理解三种 DFS 遍历的入栈差异;
  • 二叉搜索树中第 K 小的元素题解:中序遍历在 BST 上的实战应用;
  • 二叉搜索树基础教程:理解中序遍历输出有序序列的数学基础;
  • 算法题目分类列表:二叉树的遍历题目清单,可继续刷题巩固。

通过本题,建议同时掌握「递归模板 + 显式栈模拟系统栈」两种能力,前者保证面试正确率,后者应对高难度工程化约束,二者结合即可从容应对二叉树遍历的一切变体题目。

  • 教程
  • 文档
  • 知识库

【免费下载链接】AlgoNote

⛽️「算法通关手册」:从零开始的「算法与数据结构」学习教程,200 道「算法面试热门题目」,1000+ 道「LeetCode 题目解析」,持续更新中!

项目地址:https://gitcode.com/gh_mirrors/le/AlgoNote
点击查看免费下载

相关推荐

上一篇:Rax移动端图片优化:加载速度与内存占用优化方案
下一篇:7个实用技巧!掌握fastai早停法:从验证损失监控到最佳模型保存全攻略

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询