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

leetcode617.合并二叉树:迭代法中层序遍历与队列操作的深度解析

一、题目深度解析与合并规则

题目描述

合并两棵二叉树是一个经典的树结构操作问题,题目要求我们将两棵二叉树合并成一棵新二叉树。合并规则如下:

  1. 若两棵树的对应节点都存在,则将两个节点的值相加作为新节点的值
  2. 若其中一棵树的节点存在,另一棵不存在,则以存在的节点作为新节点
  3. 若两棵树的对应节点都不存在,则新节点也不存在

直观示例

输入两棵树:

树1:            树2:1                 2/ \               / \3   2             1   3/                   \   \5                     4   7

合并后结果:

     3/ \4   5/ \   \5   4   7

核心难点

  1. 对应节点同步遍历:如何保证两棵树的节点一一对应合并
  2. 迭代终止条件:明确队列操作的终止时机
  3. 节点存在状态处理:处理不同存在状态下的节点合并逻辑
  4. 队列操作顺序:设计合理的入队出队顺序保证合并正确性

二、迭代解法的核心实现与数据结构设计

完整迭代代码实现

/*** Definition for a binary tree node.* public class TreeNode {*     int val;*     TreeNode left;*     TreeNode right;*     TreeNode() {}*     TreeNode(int val) { this.val = val; }*     TreeNode(int val, TreeNode left, TreeNode right) {*         this.val = val;*         this.left = left;*         this.right = right;*     }* }*/
class Solution {public TreeNode mergeTrees(TreeNode root1, TreeNode root2) {// 特殊情况处理if (root1 == null) {return root2;}if (root2 == null) {return root1;}Deque<TreeNode> queue = new LinkedList<>();TreeNode temp1 = root1;TreeNode temp2 = root2;// 初始时将两棵树的根节点入队queue.offer(temp1);queue.offer(temp2);while (!queue.isEmpty()) {// 取出两棵树的当前节点temp1 = queue.poll();temp2 = queue.poll();// 合并当前节点值temp1.val += temp2.val;// 处理左子节点if (temp1.left != null && temp2.left != null) {// 两棵树左子节点都存在,入队继续合并queue.offer(temp1.left);queue.offer(temp2.left);} else if (temp1.left == null) {// root1左子节点为空,直接用root2的左子节点替代temp1.left = temp2.left;}// 处理右子节点if (temp1.right != null && temp2.right != null) {// 两棵树右子节点都存在,入队继续合并queue.offer(temp1.right);queue.offer(temp2.right);} else if (temp1.right == null) {// root1右子节点为空,直接用root2的右子节点替代temp1.right = temp2.right;}}return root1;}
}

核心数据结构设计:

  1. 双端队列(Deque)

    • 作用:存储两棵树的对应节点,实现层序遍历
    • 特点:支持高效的两端插入和删除,适合层序遍历的FIFO特性
    • 存储方式:每次存入两棵树的对应节点,保证同步处理
  2. 节点引用操作

    • temp1temp2:指向两棵树的当前处理节点
    • 直接修改temp1节点:实现原地合并,避免新建节点
    • 引用传递:修改temp1即修改原树结构

三、核心问题解析:队列操作与合并逻辑

1. 队列的出入队顺序设计

入队逻辑:
queue.offer(temp1.left);
queue.offer(temp2.left);
  • 顺序原则:先左后右,符合层序遍历顺序
  • 同步原则:同时存入两棵树的对应子节点,保证合并的对应关系
  • 入队条件
    • 两棵树的子节点都存在时,存入队列继续处理
    • 仅当root1的子节点为空时,用root2的子节点替代,不存入队列
出队逻辑:
temp1 = queue.poll();
temp2 = queue.poll();
  • FIFO特性:先入队的节点先处理,保证层序遍历顺序
  • 成对出队:每次取出两棵树的对应节点,确保合并的对应关系
  • 终止条件:队列为空时,所有可合并节点处理完毕

2. 节点存在状态的处理逻辑

情况1:两棵树节点都存在
if (temp1.left != null && temp2.left != null) {queue.offer(temp1.left);queue.offer(temp2.left);
}
  • 处理方式:值相加后,将两个子节点入队继续合并
  • 逻辑意义:继续处理更深层的对应节点
情况2:仅root2节点存在
else if (temp1.left == null) {temp1.left = temp2.left;
}
  • 处理方式:将root2的子节点直接赋值给root1
  • 逻辑意义:补充root1中缺失的节点,实现合并规则
情况3:仅root1节点存在
  • 代码处理:当temp2的子节点为空时,无需处理(root1的子节点保留)
  • 逻辑意义:root1的节点保留,符合合并规则

四、迭代流程深度模拟:示例合并过程解析

示例两棵树的结构:

树1:

     1/ \3   2/5

树2:

     2/ \1   3\   \4   7

队列操作详细流程:

  1. 初始状态

    • 队列:[1, 2]
    • 处理节点1和2,值合并为3,队列变为空
  2. 处理左子节点(3和1)

    • 入队:[3, 1]
    • 处理节点3和1,值合并为4
    • 左子节点5和null:5存在,null不存在,无需操作
    • 右子节点null和4:root1右子节点为空,赋值4,队列变为[5, null, 4, 3]
  3. 处理左子节点5和null

    • root2左子节点为空,root1左子节点5保留,队列变为[4, 3, null, 7]
  4. 处理右子节点4和3

    • 处理节点4和3,值合并为5
    • 左子节点null和null:都为空,无需操作
    • 右子节点null和7:root1右子节点为空,赋值7,队列变为[null, null, 7, null]
  5. 处理左子节点null和null

    • 都为空,队列变为[7, null]
  6. 处理右子节点7和null

    • root2右子节点为空,root1右子节点7保留,队列为空

最终合并结果:

     3/ \4   5/ \   \5   4   7

五、算法复杂度分析

1. 时间复杂度

  • O(min(m,n))
    • m和n分别为两棵树的节点数
    • 只访问两棵树的公共节点,公共节点数为min(m,n)
    • 每个节点仅访问一次,时间复杂度线性

2. 空间复杂度

  • O(min(m,n))
    • 队列中最多存储min(m,n)个节点
    • 最坏情况下,队列存储所有公共节点
    • 空间复杂度与树的宽度相关

3. 迭代法与递归法对比

方法优势劣势
迭代避免递归栈溢出,适合大节点数代码逻辑稍复杂,需要手动维护队列
递归代码简洁,符合树的递归定义可能因栈溢出无法处理深树

六、核心技术点总结:迭代合并的三大关键

1. 队列的双节点存储策略

  • 存储单位:每次存储两棵树的对应节点,保证合并的同步性
  • 顺序控制:先左后右的入队顺序,实现层序遍历
  • 空间效率:仅存储必要节点,不浪费空间

2. 节点存在状态的分层处理

  • 三层判断
    1. 都存在:合并值并继续入队
    2. 仅root1存在:保留root1节点
    3. 仅root2存在:用root2节点补充
  • 逻辑闭环:覆盖所有可能的节点存在状态

3. 原地修改的高效实现

  • 直接赋值temp1.left = temp2.left直接修改树结构
  • 无新建节点:避免对象创建开销,提高效率
  • 引用传递:修改temp1即修改原树,无需返回新树

七、常见误区与优化建议

1. 队列顺序错误误区

  • 错误做法:先入队右子节点,再入队左子节点
  • 正确顺序:先左后右,保证层序遍历顺序
  • 影响:顺序错误会导致节点合并顺序混乱

2. 空节点处理遗漏

  • 错误做法:只处理都存在和root1为空的情况
  • 正确处理:代码中通过else if处理root1为空的情况,root2为空时自动保留root1
  • 逻辑完整性:确保所有情况都被覆盖

3. 优化建议

  • 双队列优化:使用两个队列分别存储两棵树的节点,逻辑更清晰
  • 广度优先特性:层序遍历天然适合并行处理两棵树
  • 大型树处理:迭代法更适合处理节点数多的树,避免递归栈溢出

八、总结:迭代法在树合并中的工程价值

本算法通过层序遍历和队列操作,实现了二叉树的高效合并。其核心价值在于:

  1. 工程适用性

    • 避免递归栈溢出,适合生产环境的大型树结构
    • 空间复杂度可控,适合内存受限场景
  2. 逻辑清晰性

    • 层序遍历逻辑直观,易于理解和维护
    • 队列操作明确,适合团队协作开发
  3. 扩展性

    • 可轻松扩展为多棵树的合并
    • 可修改合并规则,适应不同业务场景

这种迭代解法充分体现了数据结构与算法的工程价值,通过队列这一基础数据结构,实现了树结构的高效操作。理解这种基于队列的层序遍历思想,对解决其他树结构问题(如树的复制、树的序列化等)具有重要的参考意义。在实际工程中,迭代法因其稳定性和效率,常用于数据库索引树操作、分布式文件系统树合并等场景。

相关文章:

  • 7.安卓逆向2-frida hook技术-介绍
  • Real2Render2Real:无需动力学仿真或机器人硬件即可扩展机器人数据
  • gin使用Mysql连接池用法
  • 【排错】kylinLinx环境python读json文件报错UTF-8 BOM
  • Linux三剑客之grep命令使用教程
  • PTA练习题
  • 区块链与Web3:如何有效保障个人数据安全
  • 深入解析操作系统内核与用户空间以及内核态与用户态转换
  • 华为OD机试_2025 B卷_返回矩阵中非1的元素个数(Python,100分)(附详细解题思路)
  • Python 实现简单OCR文本识别
  • jquery基础知识
  • 关于拓展模块NotificationStyle的demo运行时报错的问题
  • 如何清除浏览器启动hao点360
  • 攻防世界RE-reverse_re3
  • 深入解析 BlockingQueue:并发编程面试中的高频考点!
  • vue3 浮点数计算
  • 架空线路智能云台监控系统介绍
  • ODBC简介
  • UNet 改进(28):结合Coordinate Attention+FPN架构
  • 字节开源 Dolphin: 通过异构锚点提示进行文档图像解析
  • 做网站应该会什么/百度一下搜索网页
  • 52麻将官方网站做代理/北京网站优化seo
  • wordpress 仿北京时间/广东seo
  • 安徽省水利厅j建设网站/2022年新闻大事
  • 石家庄哪里做微网站/电商网站项目
  • 西宁网站建设哪家好/百度集团