当前位置: 首页 > news >正文

LeetCode 144:二叉树的前序遍历 | 递归与迭代

LeetCode 144二叉树的前序遍历 | 递归与迭代一、题目详解1.1 题目描述LeetCode 144二叉树的前序遍历Binary Tree Preorder Traversal给定一个二叉树的根节点root返回它的前序遍历结果。难度Medium示例 1输入root [1,null,2,3] 输出[1,2,3]示例 2输入root [] 输出[]示例 3输入root [1] 输出[1]1.2 题目分析前序遍历的顺序是根节点 - 左子树 - 右子树这是二叉树遍历的三种基本方式之一前序、中序、后序掌握这三种遍历方式是学习树结构的基础。二、算法实现2.1 递归实现递归是最直观的实现方式利用函数调用栈来模拟遍历过程def preorderTraversal(root): result [] def traverse(node): if not node: return # 先访问根节点 result.append(node.val) # 递归遍历左子树 traverse(node.left) # 递归遍历右子树 traverse(node.right) traverse(root) return result递归思路解析如果当前节点为空直接返回访问当前节点将值加入结果列表递归处理左子树递归处理右子树2.2 迭代实现使用显式栈来模拟递归调用def preorderTraversal_iterative(root): if not root: return [] result [] stack [root] while stack: node stack.pop() result.append(node.val) # 注意先压右子树再压左子树 # 因为栈是后进先出这样左子树会先被处理 if node.right: stack.append(node.right) if node.left: stack.append(node.left) return result迭代思路解析初始化栈将根节点入栈弹出栈顶节点访问它将右子节点入栈因为栈是LIFO后处理将左子节点入栈先处理重复直到栈为空2.3 Morris遍历O(1)空间复杂度这是一种不使用栈的遍历方法def preorderTraversal_morris(root): result [] current root while current: if not current.left: # 没有左子树直接访问当前节点 result.append(current.val) current current.right else: # 找到左子树的最右节点 predecessor current.left while predecessor.right and predecessor.right ! current: predecessor predecessor.right if not predecessor.right: # 建立线索 predecessor.right current result.append(current.val) current current.left else: # 恢复树结构 predecessor.right None current current.right return result三、复杂度分析3.1 递归实现时间复杂度O(n)每个节点访问一次空间复杂度O(h)h为树的高度最好情况平衡树O(log n)最坏情况链式树O(n)3.2 迭代实现时间复杂度O(n)每个节点入栈出栈一次空间复杂度O(h)栈的最大深度3.3 Morris遍历时间复杂度O(n)每个节点访问常数次空间复杂度O(1)只使用常量额外空间四、边界情况讨论4.1 空树root None # 输出[]4.2 单节点树root TreeNode(1) # 输出[1]4.3 只有左子树# 1 # / # 2 # / # 3 # 输出[1, 2, 3]4.4 只有右子树# 1 # \ # 2 # \ # 3 # 输出[1, 2, 3]4.5 完全二叉树# 1 # / \ # 2 3 # / \ / \ # 4 5 6 7 # 输出[1, 2, 4, 5, 3, 6, 7]五、实际应用场景5.1 树的序列化前序遍历常用于树的序列化操作def serialize(root): 将二叉树序列化为字符串 result [] def preorder(node): if not node: result.append(#) return result.append(str(node.val)) preorder(node.left) preorder(node.right) preorder(root) return ,.join(result)5.2 表达式树求值在前序表达式波兰表达式中前序遍历可以用于求值# 表达式树 # / \ # 3 * # / \ # 4 5 # 前序遍历[, 3, *, 4, 5] # 求值结果3 4 * 5 235.3 文件系统遍历在文件系统中前序遍历对应深度优先搜索# 目录结构 # root/ # ├── docs/ # │ └── readme.txt # └── src/ # └── main.py # 前序遍历[root, docs, readme.txt, src, main.py]六、总结6.1 核心要点要点说明遍历顺序根 → 左 → 右递归实现简洁直观容易理解迭代实现使用栈模拟递归适合处理大规模数据Morris遍历O(1)空间复杂度适合内存受限场景6.2 与其他遍历的对比遍历方式顺序特点前序根→左→右适合复制树、序列化中序左→根→右BST中得到有序序列后序左→右→根适合释放资源、计算子树信息层序按层访问适合求树的深度、宽度优先搜索6.3 扩展思考如何在前序遍历中记录节点的深度信息如何修改算法同时输出节点的路径信息前序遍历在哪些算法问题中是关键步骤参考资料LeetCode 144 题解二叉树遍历总结
http://www.rkmt.cn/news/1409761.html

相关文章:

  • 手把手教你用ATE测试I²C EEPROM:从PMU设置到图形文件编写的完整流程
  • 从测量铅笔到预测房价:最小二乘法在Excel和机器学习中的实战对比
  • 速腾聚创RS-M1激光雷达开箱实测:从拆箱到上电,新手避坑指南(附线缆改造建议)
  • 从Renren-Fast到微服务:手把手教你拆出公共Common模块(含依赖清单)
  • 从食材识别到营养配比,再到文化适配——ChatGPT食谱创作全流程拆解,手把手带练6类高转化场景
  • 从‘翻车’案例到优化方案:聊聊毫米波雷达天线罩那些坑(矩形vs弧形、泥水影响、PCB吸波结构)
  • 告别imgaug!用Roboflow给YOLOv8数据集做增强,5分钟搞定格式转换和扩增
  • 避障小车代码调试踩坑实录:HC-SR04测距不准、SG90舵机乱转?51单片机常见问题解决
  • 直播卡顿、花屏?从H.264的GOP、Slice到FLV封装的推流优化避坑指南
  • IC设计面试必考:边沿检测电路的5种变体与常见陷阱(附仿真对比)
  • 幻尔舵机控制板+STM32:从官方上位机到自定义动作组的无缝衔接实战
  • 数据结构学不会?试试用‘图书管理’这个例子把线性表(顺序表/链表)搞明白
  • AI 术语通俗词典:多头注意力
  • 告别RPM包!在Ubuntu 22.04上把Oracle 11g XE的安装包‘转正’成DEB格式
  • 从SE71到打印机:手把手调试SAPscript表单打印全过程(含LP01配置)
  • STM32飞控实战:如何构建稳定可靠的无人机控制系统
  • 合宙ESP32-C3的USB CDC和DIO模式,PlatformIO里到底怎么配?一次讲清
  • 初创公司如何借助Taotoken Token Plan控制AI实验成本
  • 手把手教你用AXI4-Lite配置Xilinx TEMAC的MDIO接口,搞定PHY芯片寄存器读写
  • 别再手动折腾了!用这个Shell脚本一键修复群晖PostgreSQL服务(支持DSM6/DSM7)
  • 嘉立创/捷配下单必看:PCB和钢网一起下单,这个Mark点选项千万别漏勾!
  • 随笔:宜搭根据条件搜索表单实例详情列表中如何排序
  • 手把手教你用Simulink搭建Buck变换器仿真模型(附20kHz开关频率参数设置)
  • 实测避坑:哪些安卓手机更适合跑VINS-MONO?从华为到小米的IMU数据采集体验报告
  • 别再为缺失的交通数据发愁了!手把手教你用Python实现TAS-LR时空数据重建模型
  • STM32F103定时器中断入门:用CubeMX和HAL库实现LED精准1秒闪烁(附完整代码)
  • AI智能体Wordle竞技场:LLM与规则引擎混合架构实战
  • 智能体记忆系统解析:从向量检索到OpenClaw实践
  • 原生开发Telegram Bot:从HTTP请求到高性能实现
  • SAP APO老兵实战复盘:从DP、SNP到PPDS,我们踩过的那些‘坑’与S4HANA的平滑迁移指南