589. N叉树的前序遍历迭代法:null指针与栈的巧妙配合

一、题目描述

给定一个N叉树的根节点,返回其节点值的前序遍历结果。前序遍历的定义是:先访问根节点,再依次遍历每个子节点(从左到右)。例如,对于如下N叉树:

    1/ | \3  2  4
/ \
5  6

前序遍历结果为:[1,3,5,6,2,4]

二、核心难点:null指针与迭代逻辑的设计

难点1:null指针的作用——标记节点处理阶段

在迭代法中,我们需要模拟递归的“回溯”过程。null指针在此充当阶段分隔符,用于区分以下两个阶段:

  1. 入栈子节点阶段:当遇到非null节点时,先将所有子节点逆序入栈,再将当前节点和null入栈,标记“子节点已入栈,等待处理当前节点值”。
  2. 收集节点值阶段:当遇到null时,说明其前一个节点的子节点已全部入栈,此时弹出该节点并收集值(类似递归中的“回溯时处理”)。

难点2:迭代逻辑的核心——栈的状态控制

  • 子节点逆序入栈:由于栈是后进先出(LIFO),将子节点按逆序入栈(如[C,B,A]入栈,弹出顺序为A,B,C),确保前序遍历的顺序(根→A→B→C)。
  • 双栈操作:通过“非null节点入栈子节点→入栈自身和null”的模式,确保在处理完所有子节点后,才会处理当前节点值,避免重复访问。

三、代码解析:迭代法的完整实现

import java.util.*;class Solution {public List<Integer> preorder(Node root) {List<Integer> res = new ArrayList<>();if (root == null) return res;Stack<Node> stack = new Stack<>();stack.push(root); // 根节点入栈while (!stack.isEmpty()) {Node node = stack.pop(); // 弹出节点if (node != null) {// 1. 逆序入栈所有子节点if (node.children != null) {for (int i = node.children.size() - 1; i >= 0; i--) {stack.push(node.children.get(i));}}// 2. 入栈当前节点和null(标记处理阶段)stack.push(node);stack.push(null);} else {// 遇到null,说明前一个节点的子节点已处理完毕,收集当前节点值Node valNode = stack.pop();res.add(valNode.val);}}return res;}
}

四、迭代流程模拟:以示例N叉树为例

初始状态

  • 栈:[1]
  • 结果:[]

第一次循环

  1. 弹出1(非null):
    • 子节点为[3,2,4],逆序入栈为4,2,3
    • 入栈1null,栈变为:[4,2,3,1,null]

第二次循环

  1. 弹出null
    • 弹出1,加入结果[1]
    • 栈变为:[4,2,3]

第三次循环

  1. 弹出3(非null):
    • 子节点为[5,6],逆序入栈为6,5
    • 入栈3null,栈变为:[4,2,6,5,3,null]

第四次循环

  1. 弹出null
    • 弹出3,加入结果[1,3]
    • 栈变为:[4,2,6,5]

第五次循环

  1. 弹出5(非null,无子节点):
    • 入栈5null,栈变为:[4,2,6,5,null]

第六次循环

  1. 弹出null
    • 弹出5,加入结果[1,3,5]
    • 栈变为:[4,2,6]

后续循环

  • 类似流程处理624,最终结果为[1,3,5,6,2,4]

五、关键知识点:前序与后序迭代法的对比

前序遍历(当前代码)

  • 核心逻辑
    非null节点→逆序入栈子节点→入栈自身和null
    确保先处理子节点,再通过null触发收集当前节点值。

后序遍历(修改版代码)

public List<Integer> postorder(Node root) {List<Integer> res = new ArrayList<>();if (root == null) return res;Stack<Node> stack = new Stack<>();stack.push(root);while (!stack.isEmpty()) {Node node = stack.pop();if (node != null) {stack.push(node); // 先入栈当前节点stack.push(null); // 标记后序处理// 正序入栈子节点(与前序相反)if (node.children != null) {for (Node child : node.children) {stack.push(child);}}} else {Node valNode = stack.pop();res.add(valNode.val); // 后序收集}}return res;
}
  • 关键修改
    1. 子节点正序入栈(前序为逆序),确保后序遍历顺序(左→右→根)。
    2. null标记后处理当前节点,确保子节点先被处理。

六、null指针的本质:模拟递归的压栈与回溯

递归流程迭代(栈+null)模拟
调用preorder(root)stack.push(root)
递归前序遍历子节点逆序入栈子节点,压栈root和null
回溯时处理root.val遇到null,弹出root并收集值

null指针的作用相当于递归中的“回溯点”,通过栈的状态机控制,将递归的隐式调用栈转化为显式的栈操作,实现非递归算法。

七、总结:迭代法的优势与适用场景

优势

  • 空间可控:避免递归深度过大导致的栈溢出(如树高为1e5时)。
  • 灵活性:可方便修改为后序、层序等其他遍历方式(只需调整入栈顺序和标记逻辑)。

适用场景

  • 所有需要深度优先遍历(DFS)的树结构问题,尤其是N叉树(递归可能复杂)。
  • 面试中要求“非递归”解法的场景。

核心思想

通过栈模拟递归的调用栈,利用null等标记符区分节点的“预处理阶段”和“回溯处理阶段”,实现对遍历顺序的精确控制。理解这一思想后,可举一反三解决二叉树、N叉树的各种遍历问题。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/bicheng/81298.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

显性知识的主要特征

有4个主要特征&#xff1a; 客观存在性静态存在性可共享性认知元能性

奥运数据可视化:探索数据讲述奥运故事

在数据可视化的世界里&#xff0c;体育数据因其丰富的历史和文化意义&#xff0c;常常成为最有吸引力的主题之一。今天我要分享一个令人着迷的奥运数据可视化项目&#xff0c;它巧妙地利用交互式图表和动态动画&#xff0c;展现了自1896年至今奥运会的发展历程和各国奥运成就的…

Mysql存储过程(附案例)

​ 文章目录 存储过程概述1、基本语法2、变量①、系统变量②、用户自定义变量③、局部变量 3、流程控制语句①、if语句②、参数③、case语句④、while语句⑤、repeat语句⑥、loop语句⑦、cursor游标⑧、handler 4、存储函数 存储过程概述 存储过程是事先经过编译并存储在数据…

小波变换+注意力机制成为nature收割机

小波变换作为一种新兴的信号分析工具&#xff0c;能够高效地提取信号的局部特征&#xff0c;为复杂数据的处理提供了有力支持。然而&#xff0c;它在捕捉数据中最为关键的部分时仍存在局限性。为了弥补这一不足&#xff0c;我们引入了注意力机制&#xff0c;借助其能够强化关注…

SQLMesh 增量模型从入门到精通:5步实现高效数据处理

本文深入解析 SQLMesh 中的增量时间范围模型&#xff0c;介绍其核心原理、配置方法及高级特性。通过实际案例说明如何利用该模型提升数据加载效率&#xff0c;降低计算资源消耗&#xff0c;并提供配置示例与最佳实践建议&#xff0c;帮助读者在实际项目中有效应用这一强大功能。…

Android应用内存分析与优化 - 工具篇之Booster

序 在原理篇中&#xff0c;我们发现在App内存的分布中&#xff0c;Code是占大头的部分&#xff0c;所以我们可以从App体积方面想办法&#xff0c;通过减小App体积达到降低内存的目的&#xff0c;同时&#xff0c;根据权威的机构分析&#xff0c;体积与用户下载和留存有很大的联…

金属加工液展|切削液展|2025上海金属加工液展览会

2025上海金属加工液展览会 时间&#xff1a;2025年12月2-4日 地点&#xff1a;上海新国际博览中心 2025上海金属加工液展规划30000平方米展览规模&#xff0c;预设展位1200个&#xff0c;将为国内外加工液产业提供一个集“展示、合作、交易、发展”于一体的综合性平台&#…

React学习———Redux 、 React Redux和react-persist

Redux Redux是一个流行的JavaScript状态管理库&#xff0c;通常用于React等前端框架结合使用。Redux 的设计思想是让应用的状态变得可预测、可追踪、易于调试和测试。 Redux的核心l理念 单一数据源&#xff1a;整个应用的状态被存储在一个唯一的Store对象中&#xff0c;所有…

Python字符串常用方法详解

文章目录 Python字符串常用方法详解一、字符串大小写转换方法(常用)1. 基础大小写转换2. 案例&#xff1a;验证码检查&#xff08;不区分大小写&#xff09; 二、字符串查找与替换方法1. 查找相关方法2. 替换相关方法 三、字符串判断方法1. 内容判断方法 四、字符串分割与连接方…

MyBatis—动态 SQL

MyBatis—动态 SQL 一、动态 SQL 的核心作用 动态 SQL 主要解决以下问题&#xff1a; 灵活性&#xff1a;根据不同的输入参数生成不同的 SQL 语句&#xff08;如条件查询、批量操作&#xff09;。 可维护性&#xff1a;减少重复代码&#xff0c;通过标签化逻辑提高 SQL 可读…

Python机器学习笔记(二十五、算法链与管道)

对于许多机器学习算法,特定数据表示非常重要。首先对数据进行缩放,然后手动合并特征,再利用无监督机器学习来学习特征。因此,大多数机器学习应用不仅需要应用单个算法,而且还需要将许多不同的处理步骤和机器学习模型链接在一起。Pipeline类可以用来简化构建变换和模型链的…

YOLOv3深度解析:多尺度特征融合与实时检测的里程碑

一、YOLOv3的诞生&#xff1a;继承与突破的起点 YOLOv3作为YOLO系列的第三代算法&#xff0c;于2018年由Joseph Redmon等人提出。它在YOLOv2的基础上&#xff0c;针对小目标检测精度低、多类别标签预测受限等问题进行了系统性改进。通过引入多尺度特征图检测、残差网络架构和独…

已解决(亲测有效!):安装部署Docker Deskpot之后启动出现Docker Engine Stopped!

文章目录 已解决&#xff1a;安装部署Docker Deskpot之后启动出现Docker Engine Stopped&#xff01;个人环境介绍自己的解决问题思路&#xff08;详细过程附截图&#xff09;1.打开控制面板2.点击程序和功能3.点击启动或关闭windows功能4.Hyper-V5.右键菜单栏的windows图标点击…

PCIE接收端检测机制分析

PCIE接收端检测机制分析 1、PCIE的接收端检测机制 接收器检测电路作为发射器的一部分实现&#xff0c;必须正确检测是否存在与ZRX-DC参数&#xff08;40Ω-60Ω&#xff09;隐含的直流阻抗等效的负载阻抗。 接收器检测序列的推荐行为如下&#xff1a; ‌初始状态‌&#xff…

[模型部署] 3. 性能优化

&#x1f44b; 你好&#xff01;这里有实用干货与深度分享✨✨ 若有帮助&#xff0c;欢迎&#xff1a;​ &#x1f44d; 点赞 | ⭐ 收藏 | &#x1f4ac; 评论 | ➕ 关注 &#xff0c;解锁更多精彩&#xff01;​ &#x1f4c1; 收藏专栏即可第一时间获取最新推送&#x1f514;…

InternVL3: 利用AI处理文本、图像、视频、OCR和数据分析

InternVL3推动了视觉-语言理解、推理和感知的边界。 在其前身InternVL 2.5的基础上,这个新版本引入了工具使用、GUI代理操作、3D视觉和工业图像分析方面的突破性能力。 让我们来分析一下是什么让InternVL3成为游戏规则的改变者 — 以及今天你如何开始尝试使用它。 InternVL…

鸿蒙 ArkUI - ArkTS 组件 官方 UI组件 合集

ArkUI 组件速查表 鸿蒙应用开发页面上需要实现的 UI 功能组件如果在这 100 多个组件里都找不到&#xff0c;那就需要组合造轮子了 使用技巧&#xff1a;先判断需要实现的组件大方向&#xff0c;比如“选择”、“文本”、“信息”等&#xff0c;或者是某种形状比如“块”、“图…

HTTP GET报文解读

考虑当浏览器发送一个HTTP GET报文时&#xff0c;通过Wireshark 俘获到下列ASCII字符串&#xff1a; GET /cs453/index.html HTTP/1.1 Host: gaia.cs.umass.edu User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7.2) Gecko/20040804 Netscape/7.2 (ax) Acc…

【Linux网络】数据链路层

数据链路层 用于两个设备&#xff08;同一种数据链路节点&#xff09;之间进行传递。 认识以太网 “以太网” 不是一种具体的网络&#xff0c;而是一种技术标准&#xff1b;既包含了数据链路层的内容&#xff0c;也包含了一些物理层的内容。例如&#xff1a;规定了网络拓扑结…

【打破信息差】萌新认识与入门算法竞赛

阅前须知 XCPC萌新互助进步群2️⃣&#xff1a;174495261 博客主页&#xff1a;resot (关注resot谢谢喵) 针对具体问题&#xff0c;应当进行具体分析&#xff1b;并无放之四海而皆准的方法可适用于所有人。本人尊重并支持每位学习者对最佳学习路径的自主选择。本篇所列训练方…