leetcode617.合并二叉树:递归思想下的树结构融合艺术

news2025/6/1 7:15:26

一、题目深度解析与核心规则

题目描述

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

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

直观示例

输入两棵树:

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

合并后结果:

     3
    / \
   4   5
  / \   \
 5   4   7

核心难点

  1. 对应节点的定位:如何保证两棵树的节点一一对应合并
  2. 递归终止条件:明确什么情况下停止递归合并
  3. 节点值的合并策略:处理不同存在状态下的节点合并逻辑

二、递归解法的核心实现与逻辑框架

完整递归代码实现

/**
 * 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) {
        // 终止条件1:root1为空时,直接返回root2(无论root2是否为空)
        if (root1 == null) return root2;
        // 终止条件2:root2为空时,直接返回root1(此时root1一定非空)
        if (root2 == null) return root1;
        
        // 合并当前节点:值相加
        root1.val += root2.val;
        
        // 递归合并左子树
        root1.left = mergeTrees(root1.left, root2.left);
        // 递归合并右子树
        root1.right = mergeTrees(root1.right, root2.right);
        
        return root1; // 返回合并后的根节点
    }
}

代码核心设计解析:

  1. 输入输出设计

    • 输入:两棵二叉树的根节点root1root2
    • 输出:合并后的二叉树的根节点
    • 特点:直接修改root1节点,避免创建新树的空间开销
  2. 递归合并策略

    • 采用深度优先递归方式
    • 先合并根节点,再递归合并左右子树
    • 符合"根-左-右"的前序遍历顺序
  3. 节点存在状态处理

    • 空节点处理优先于值合并
    • 通过递归终止条件处理三种存在状态(都存在/仅一者存在/都不存在)

三、核心逻辑解析:递归合并的三重境界

1. 终止条件的哲学:空节点的处理艺术

if (root1 == null) return root2;
if (root2 == null) return root1;
  • 终止条件的逻辑分层

    1. root1为空,无论root2是否为空,直接返回root2
      • 包含两种情况:
        • root2非空:root2作为合并结果
        • root2为空:返回空(两者都为空)
    2. root2为空,此时root1必非空(因为已跳过条件1),返回root1
  • 空节点处理的本质
    实现了"存在优先"原则,确保非空节点保留,空节点被替代

2. 根节点的合并:值的融合逻辑

root1.val += root2.val;
  • 合并前提:此时root1root2都非空(已通过终止条件过滤)
  • 操作本质:将两棵树对应节点的值相加,存储在root1
  • 副作用:直接修改root1节点的值,避免新建节点

3. 子树的递归合并:结构的递归融合

root1.left = mergeTrees(root1.left, root2.left);
root1.right = mergeTrees(root1.right, root2.right);
  • 递归参数
    • 左子树合并:root1.leftroot2.left
    • 右子树合并:root1.rightroot2.right
  • 返回值赋值
    • 将合并后的子树重新赋值给root1的对应位置
    • 实现了root1树的原地修改
  • 递归本质
    将整树的合并分解为左右子树的合并,符合分治思想

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

示例两棵树的结构:

树1:

     1
    / \
   3   2
  /
 5

树2:

     2
    / \
   1   3
    \   \
     4   7

递归合并步骤:

  1. 根节点合并(1和2)

    • root1.val = 1+2=3
    • 递归合并左子树(3和1)、右子树(2和3)
  2. 合并左子树(3和1)

    • root1.val = 3+1=4
    • 递归合并左子树(5和null)、右子树(null和4)
  3. 合并左子树(5和null)

    • root1=5(root2为空,返回root1)
    • 左子树合并结果为5,赋值给4的左子节点
  4. 合并右子树(null和4)

    • root1=null,返回root2=4
    • 右子树合并结果为4,赋值给4的右子节点
  5. 合并根节点的右子树(2和3)

    • root1.val=2+3=5
    • 递归合并左子树(null和null)、右子树(null和7)
  6. 合并左子树(null和null)

    • 都为空,返回null,赋值给5的左子节点
  7. 合并右子树(null和7)

    • root1=null,返回root2=7,赋值给5的右子节点

最终合并结果:

     3
    / \
   4   5
  / \   \
 5   4   7

五、算法复杂度分析

1. 时间复杂度

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

2. 空间复杂度

  • O(h)
    • h为递归栈的最大深度,即树的高度
    • 最坏情况下(树退化为链表),空间复杂度O(min(m,n))
    • 平均情况下,空间复杂度O(log(min(m,n)))

3. 算法优势

  • 原地修改:直接修改root1树,无需创建新节点
  • 递归简洁:代码量少,逻辑清晰,符合树的递归定义
  • 高效合并:时间复杂度线性,空间复杂度对数级

六、核心技术点总结:递归合并的三大法则

1. 空节点优先法则

  • 先处理空节点情况,再处理非空节点
  • 空节点处理逻辑包含三种状态:
    • root1空→返回root2
    • root2空→返回root1
    • 都空→返回空(隐含在root1空的情况中)

2. 根先于子树法则

  • 遵循"根-左-右"的前序顺序
  • 先合并根节点,再递归合并子树
  • 符合树结构的递归定义

3. 原地修改法则

  • 直接修改root1节点,而非创建新树
  • 节省空间开销,提高效率
  • 返回root1实现链式合并

七、常见误区与边界情况处理

1. 新建节点误区

  • 错误做法:创建新节点存储合并结果
  • 正确做法:原地修改root1节点
  • 优势:减少内存分配,提高效率

2. 递归顺序误区

  • 错误顺序:先合并子树再合并根节点
  • 正确顺序:先合并根节点,再合并子树
  • 逻辑原因:根节点的合并依赖于自身值,与子树无关

3. 边界情况处理

  • 情况1:两棵空树:返回空树
  • 情况2:一棵空树:返回另一棵树
  • 情况3:深度不同的树:深度小的树的空节点被深度大的树的节点补充

八、总结:递归思想在树合并中的完美体现

本算法通过简洁的递归实现,完美解决了二叉树的合并问题。其核心思想包括:

  1. 递归定义匹配:利用树的递归定义,将整树合并分解为节点合并和子树合并
  2. 空节点处理优先:通过前置条件处理空节点,简化合并逻辑
  3. 原地修改策略:直接修改原树节点,避免额外空间开销

这种递归解法不仅代码简洁,而且效率优良,充分体现了递归在树结构操作中的优势。理解这种合并逻辑,对解决其他树结构问题(如树的复制、树的比较等)具有重要的参考价值。在实际工程中,这种原地修改的递归策略也常用于需要高效处理树结构的场景,如数据库索引树的更新、文件系统树的合并等。

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

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

相关文章

深度学习入门:从零搭建你的第一个神经网络

深度学习入门:从零搭建你的第一个神经网络 系统化学习人工智能网站(收藏):https://www.captainbed.cn/flu 文章目录 深度学习入门:从零搭建你的第一个神经网络摘要引言第一章:神经网络基础原理1.1 神经元…

【Python办公】Excel简易透视办公小工具

目录 专栏导读1. 背景介绍2. 功能介绍3. 库的安装4. 界面展示5. 使用方法6. 实际应用场景7. 优化方向完整代码总结专栏导读 🌸 欢迎来到Python办公自动化专栏—Python处理办公问题,解放您的双手 🏳️‍🌈 博客主页:请点击——> 一晌小贪欢的博客主页求关注 👍 该系…

Linux系列-2 Shell常用命令收集

背景 本文用于收集Linux常用命令(基于Centos7),是一个持续更新的博客,建议收藏,编写shell时遇到问题可以随时查阅。 1.Shell类型 shell是用C语言编写的程序,作为命令解释器连接着用户和操作系统内核。常见的shell有sh(Bourne She…

MATLAB使用多个扇形颜色变化表示空间一个点的多种数值

MATLAB使用多个扇形颜色变化表示空间一个点的多种数值 excel中表格中数据格式,多行 lonlatdata1data2data3117380.11100 clear;close all; figure(Position,[100 100 800 800]);num_points 14; [num,txt,raw] xlsread(test.xlsx); x num(:,1); y num(:,2);d…

CAD精简多段线顶点、优化、删除多余、重复顶点——CAD c#二次开发

附部分代码如下: public static void Pl精简(){Document doc Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument;Database db doc.Database;Editor ed doc.Editor;var plOrigon db.SelectCurve("\n选择多段线:");…

输电线路的“智慧之眼”:全天候可视化监测如何赋能电网安全运维

在电力需求持续攀升、电网规模日益庞大的今天,输电线路的安全稳定运行面临着前所未有的挑战。线路跨越地形复杂多变,尤其是在偏远山区、铁路沿线及恶劣天气条件下,传统的人工巡检方式显得力不从心——效率低、风险高、覆盖有限。如何实现更智…

两阶段法目标检测发展脉络

模式识别期末展示大作业,做个记录,希望大家喜欢。 R-CNN Fast R-CNN R-FCN 整个过程可以分解为以下几个步骤: 输入图像 (image) 和初步特征提取 (conv, feature maps): 首先,输入一张原始图像,经过一系列…

小白的进阶之路系列之六----人工智能从初步到精通pytorch数据集与数据加载器

本文将介绍以下内容: 数据集与数据加载器 数据迁移 如何建立神经网络 数据集与数据加载器 处理数据样本的代码可能会变得混乱且难以维护;理想情况下,我们希望我们的数据集代码与模型训练代码解耦,以获得更好的可读性和模块化。PyTorch提供了两个数据原语:torch.utils…

NestJS——重构日志、数据库、配置

个人简介 👀个人主页: 前端杂货铺 🙋‍♂️学习方向: 主攻前端方向,正逐渐往全干发展 📃个人状态: 研发工程师,现效力于中国工业软件事业 🚀人生格言: 积跬步…

c++数据结构8——二叉树的性质

一、二叉树的基本性质 示图1: 性质1:层节点数上限 在一棵二叉树中,第i层至多有2^{i-1}个节点(首层是第1层) 这个性质可以通过数学归纳法证明: 第1层:2^{1-1}2^01个节点(根节点&am…

Window Server 2019--08 网络负载均衡与Web Farm

本章要点 1、了解网络负载均衡技术 2、掌握Web Farm核心原理 3、掌握如何使用Windows NLB搭建Web Farm环境 网络负载均衡技术将外部计算机发送的连接请求均匀的分配到服务器集群中的每台服务器上,接受到请求的服务器独立地响应客户的请求。 网络负载均衡技术还…

SpringBoot:统一功能处理、拦截器、适配器模式

文章目录 拦截器什么是拦截器?为什么要使用拦截器?拦截器的使用拦截路径执行流程典型应用场景DispatcherServlet源码分析 适配器模式适配器模式定义适配器模式角色适配器模式的实现适配器模式应用场景 统⼀数据返回格式优点 统一处理异常总结 拦截器 什…

AI Agent工具全景解析:从Coze到RAGflow,探索智能体自动化未来!

在人工智能技术持续深入行业应用的背景下,越来越多的企业和个人寻求通过自动化技术来提高效率和减少重复性劳动,AI Agent的崛起已经成为了不可忽视的趋势。AI Agent,即人工智能代理,是一种基于先进的人工智能技术,特别…

Onvif协议:IPC客户端开发-IPC相机控制(c语言版)

前言: 本博文主要是借鉴OceanStar大神的博文,在他的博文的基础之上做了一部分修改与简化。 博文链接: Onvif协议:IPC客户端开发之鉴权_onvif鉴权方式-CSDN博客 Onvif协议:IPC客户端开发之PTZ控制_onvif ptz-CSDN博客…

如何最简单、通俗地理解Pytorch?神经网络中的“梯度”是怎么自动求出来的?PyTorch的动态计算图是如何实现即时执行的?

PyTorch是一门科学——现代深度学习工程中的一把锋利利器。它的简洁、优雅、强大,正在让越来越多的AI研究者、开发者深度应用。 1. PyTorch到底是什么?为什么它重要? PyTorch是一个开源的深度学习框架,由Facebook AI Research(FAIR)于2016年发布,它的名字由两个部分组成…

QT+opecv如何更改图片的拍摄路径

如何更改相机拍摄图片的路径 前言:基础夯实:效果展示:实现功能:遇到问题:未解决: 核心代码: 前言: 最近在项目开发中遇到需要让用户更改相机拍摄路径的问题,用户可自己选…

秋招Day11 - JVM - 类加载机制

了解类的加载机制吗? JVM是运行Java字节码,也就是运行.class文件的虚拟机,JVM把.class文件中描述类的数据结构加载到内存中,并对数据进行校验,解析和初始化,最终转化为JVM可以使用的类型(Klass…

Webug4.0靶场通关笔记03- 第3关SQL注入之时间盲注(手注法+脚本法 两种方法)

目录 一、源码分析 1.分析闭合 2.分析输出 (1)查询成功 (2)查询失败 (3)SQL语句执行报错 二、第03关 延时注入 1.打开靶场 2.SQL手注 (1)盲注分析 (2&#xf…

Vert.x学习笔记-什么是Handler

Vert.x学习笔记 在Vert.x中,Handler是一个核心概念,用于处理异步事件和回调。它是Vert.x响应式编程模型的核心组件之一,通过函数式接口的方式简化了异步编程的复杂性。 1. Handler的定义 Handler是一个函数式接口,定义如下&#…

【Echarts】象形图

目录 效果代码 效果 代码 <!-- 业务类型 --> <template><div class"ywlx" :style"{ --height: height }"><div class"header_count count_linear_bg"><div>当月业务总量<span class"common_count text_s…