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

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

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

题目描述

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

  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. 原地修改策略:直接修改原树节点,避免额外空间开销

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

相关文章:

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

一、题目深度解析与核心规则 题目描述 合并两棵二叉树是一个经典的树结构操作问题,题目要求我们将两棵二叉树合并成一棵新二叉树。合并规则如下: 若两棵树的对应节点都存在,则将两个节点的值相加作为新节点的值若其中一棵树的节点存在&…...

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

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

【HTML-13】HTML表格合并技术详解:打造专业数据展示

表格是HTML中展示结构化数据的重要元素,而表格合并则是提升表格表现力的关键技术。本文将全面介绍HTML中的表格合并方法,帮助您创建更专业、更灵活的数据展示界面。 1. 表格合并基础概念 在HTML中,表格合并主要通过两个属性实现&#xff1a…...

鸿蒙OSUniApp 制作自定义的进度条组件#三方框架 #Uniapp

使用 UniApp 制作自定义的进度条组件 在移动应用开发中,进度条是非常常见的 UI 组件,无论是文件上传、下载、任务进度还是表单填写反馈,进度条都能为用户提供直观的进度提示。虽然 UniApp 提供了一些基础的进度条能力,但在实际项…...

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

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

m1 运行renrenfastvue出现的问题和解决方案

1. chromedriver 报错解决:执行 npm install --ignore-scripts。 2. node-sass 报错 "Node Sass does not yet support your current environment: OS X Unsupported ...": - 降低 Node 版本至 14。 - 安装版本控制工具:sudo npm insta…...

开源模型应用落地-qwen模型小试-Qwen3-8B-推理加速-vLLM-Docker(二)

一、前言 在AI模型部署效率竞争日益激烈的当下,如何将前沿大模型与高效推理框架结合,成为开发者关注的焦点。Qwen3-8B作为阿里云推出的混合推理模型,凭借80亿参数规模与128K超长上下文支持,展现了“快思考”与“慢思考”的协同能力,而vLLM框架则通过优化内存管理与并行计算…...

【C/C++】记录一次麻烦的Kafka+Json体验

文章目录 麻烦的KafkaJson体验1 目标2 工程搭建2.1 docker配置2.2 代码2.3 工程压缩包 3 执行结果 麻烦的KafkaJson体验 1 目标 初心:结合kafka json docker,验证基本的数据生产/消费。 Kafka 配合 JSON 工具,主要是为了数据的序列化和反…...

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…...

mysql:MVCC机制

MVCC机制 MVCC机制主要是mysql的多版本并发控制的一个机制,它主要是允许mysql去保存同一时间对同一份数据的不同历史版本的,从而避免读写之间的锁竞争,从而去提高并发的性能。 像传统的锁机制(读写互斥锁(Read-Write …...

Vue3 + Element Plus 实现树形结构的“单选 + 只选叶子节点 + 默认选中第一个子节点”

在 Vue 项目中&#xff0c;我们常使用树形结构组件来展示层级数据。本文将介绍如何使用 Element Plus 的 <el-tree> 组件&#xff0c;在 Vue3 中实现以下需求&#xff1a; ✅ 只能勾选叶子节点 ✅ 每次只能选中一个节点&#xff08;单选&#xff09; ✅ 页面加载时默认…...

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选择多段线&#xff1a;");…...

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

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

Spring 核心知识点补充

Spring 核心知识点补充 1. IoC&#xff08;控制反转&#xff09; 核心思想&#xff1a;将对象的创建和依赖管理交给容器&#xff0c;而非在代码中直接控制实现方式&#xff1a; XML 配置&#xff1a;<bean> 标签定义对象注解&#xff1a;Component, Service, Repositor…...

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

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

Flannel 支持的后端

Flannel 是一个为 Kubernetes 设计的容器网络解决方案&#xff0c;支持多种后端&#xff08;backend&#xff09;来处理节点间的数据包转发。根据官方文档和其他可靠来源&#xff0c;以下是 Flannel 支持的后端类型及其说明&#xff1a; VXLAN&#xff08;推荐&#xff09; 描述…...

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

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

SQL进阶之旅 Day 5: 常用函数与表达式

【SQL进阶之旅 Day 5】常用函数与表达式 在SQL的进阶学习中&#xff0c;掌握常用函数和表达式是提升查询效率、解决复杂业务问题的关键。本篇文章将深入探讨聚合函数、日期函数、条件表达式等核心内容&#xff0c;并结合实际案例分析其应用价值。通过理论讲解、代码示例和性能…...

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

个人简介 &#x1f440;个人主页&#xff1a; 前端杂货铺 &#x1f64b;‍♂️学习方向&#xff1a; 主攻前端方向&#xff0c;正逐渐往全干发展 &#x1f4c3;个人状态&#xff1a; 研发工程师&#xff0c;现效力于中国工业软件事业 &#x1f680;人生格言&#xff1a; 积跬步…...

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

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

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

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

arcgis字段计算器中计算矢量面的每个点坐标

python脚本 函数 def ExportCoordinates(feat):coors = []partnum = 0partcount = feat.partCountwhile partnum < partcount:part = feat.getPart(partnum)pnt = part.next()while pnt:coors.append("({}, {})".format(pnt.X,pnt.Y))pnt = part.next()if not p…...

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

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

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

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

GitLab CI流水线权限隔离

方案概述 本方案实现在GitLab CI/CD中根据不同人员的权限级别执行不同的流水线步骤&#xff0c;主要基于GitLab的以下特性&#xff1a; rules 条件判断variables 变量传递only/except 条件限制用户权限API查询 基础权限模型设计 1. 用户角色定义 角色描述对应GitLab权限De…...

xcode卡死问题,无论打开什么程序xcode总是在转菊花,重启电脑,卸载重装都不行

很可能是因为我们上次没有正常关闭Xcode&#xff0c;而Xcode保留了上次错误的一些记录&#xff0c;而这次打开Xcode依然去加载错误的记录&#xff0c;所以必须完全删除这些记录Xcode才能加载正常的项目。 那么也就是说&#xff0c;我们是不是只需要删除这部分错误记录文件就可以…...

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

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

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

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

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

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