【LeetCode刷题日记】617.合并二叉树(空间换安全,还是原地省内存)

🔥个人主页:北极的代码(欢迎来访)

🎬作者简介:java后端学习者

❄️个人专栏:苍穹外卖日记SSM框架深入JavaWeb

命运的结局尽可永在,不屈的挑战却不可须臾或缺!

前言:

大家好,我是代码不加冰,在这里先祝大家周末愉快!然后来到我们每日刷题的环节,嗯,在此之前我都是想着上午刷题,然后顺带着把文章发了,但是每次上午都有课,然后有时候还起不来,所以每次都拖到了下午甚至晚上,如果有时间还是每天多刷几题,感觉进度有点慢了,效率不是很高。


摘要:

本文介绍了合并两棵二叉树的两种方法:原地修改法和新建树法。原地修改法直接在root1上进行节点值相加,节省空间但会破坏原树结构;新建树法则创建全新节点,保留原树但消耗更多内存。两种方法均采用深度优先搜索递归实现,时间复杂度均为O(min(m,n))。文章通过代码对比和优缺点分析,帮助开发者根据实际需求选择合适方案,强调了在内存敏感场景下原地修改的优势,以及在需要保留原树时的新建树方案。


题目背景:617.合并二叉树

给你两棵二叉树: root1root2

想象一下,当你将其中一棵覆盖到另一棵之上时,两棵树上的一些节点将会重叠(而另一些不会)。你需要将这两棵树合并成一棵新二叉树。合并的规则是:如果两个节点重叠,那么将这两个节点的值相加作为合并后节点的新值;否则,不为 null 的节点将直接作为新二叉树的节点。

返回合并后的二叉树。

注意: 合并过程必须从两个树的根节点开始。

示例 1:

复制代码
输入:root1 = [1,3,2,5], root2 = [2,1,3,null,4,null,7]
输出:[3,4,5,5,4,null,7]

示例 2:

复制代码
输入:root1 = [1], root2 = [1,2]
输出:[2,2]

提示:

  • 两棵树中的节点数目在范围 [0, 2000]
  • -104 <= Node.val <= 104

题目分析:

整体思路

我们拿到这个题目,先分析题目需求,合并二叉树,先从整体上来看就是把两个二叉树进行叠加。之后就是细微的操作,相同节点位置的进行节点值的相加,依次叠加,思维不难,具体代码可能看着不是很好实现,我们一起来看看吧。

代码思路:

首先我们就要考虑如何找到两棵二叉树的节点位置,那么自然就是遍历了,这里用什么遍历方法呢,其实这里并没有要求,因此三种方法都可以。

关键是要同时遍历两棵树。合并的方式有两种:

创建新树:每次创建新节点,值由两棵树对应节点的值决定(都有则相加,只有一棵则取该值)

原地修改:复用第一棵树的结构,将其值加上第二棵树对应位置的值

无论哪种方式,当两棵树的对应节点都存在时,新节点的值需要两棵树共同提供;若只有一棵树有节点,则直接继承该节点。

具体操作:

利用递归的方式来实现

1.那么首先我们就要先确定递归函数的需要传入的参数和返回值

我们既然要同时遍历两颗树,那么传入的参数自然就是两棵二叉树的根节点,返回值自然就是新的构建的合并二叉树的根节点,之后依次递归


2.然后确定终止条件

因为是传入了两个树,那么就有两个树遍历的节点t1 和 t2,如果t1 == NULL 了,两个树合并就应该是 t2 了(如果t2也为NULL也无所谓,合并之后就是NULL)。

反过来如果t2 == NULL,那么两个数合并就是t1(如果t1也为NULL也无所谓,合并之后就是NULL)。


3.确定单层递归的逻辑

在这里我们需要明确的是,我们这里利用的并不是直接构建了一棵新的树,而是在第一棵树的基础上进行的叠加。但同时也会破坏原来的树,但是节省内存(不创建新节点)


深度优先搜索(原地修改)

思路: 直接在 root1 上进行修改,将 root2 的值合并到 root1 上,节省空间。

java 复制代码
/**
 * 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;
        
        // 直接在root1上修改
        root1.val += root2.val;
        root1.left = mergeTrees(root1.left, root2.left);
        root1.right = mergeTrees(root1.right, root2.right);
        
        return root1;
    }
}

我们也可以自己构建一个新的树

深度优先搜索(DFS)递归

思路: 同时遍历两棵树,对应位置相加后创建新节点,递归处理左右子树。

只需要自己构建一个新的根节点即可。

java 复制代码
java

/**
 * 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;
        
        // 两棵树都不为空:创建新节点,值为两节点值之和
        TreeNode merged = new TreeNode(root1.val + root2.val);
        
        // 递归合并左右子树
        merged.left = mergeTrees(root1.left, root2.left);
        merged.right = mergeTrees(root1.right, root2.right);
        
        return merged;
    }
}

代码对比

对比项 方法一(创建新树) 方法二(原地修改)
核心代码 TreeNode merged = new TreeNode(root1.val + root2.val) root1.val += root2.val
是否创建新节点 ✅ 是,每层递归都 new ❌ 否,直接在原节点上修改
是否修改原树 ❌ 否,root1和root2保持不变 ✅ 是,root1被改变
返回结果 返回新创建树的根节点 返回修改后的root1

优缺点对比

维度 方法一(创建新树) 方法二(原地修改)
空间复杂度 O(min(m,n)) + 新树空间 O(min(m,n))
额外内存 需要创建新节点(约 m+n 个节点) 几乎无额外内存
是否破坏原数据 ❌ 不破坏 ✅ 破坏 root1
函数纯度 ✅ 纯函数,无副作用 ❌ 有副作用
可重入性 ✅ 可重复调用 ❌ 原数据被改后无法恢复

结语:

如果对你有帮助,请**点赞,关注,收藏,**你的支持就是我最大的鼓励!

相关推荐
karry_k11 小时前
MyBatis批量insert-select踩坑:useGeneratedKeys=true 可能让PostgreSQL返回大量插入结果
java·后端
karry_k12 小时前
PostgreSQL 在 MyBatis 中执行正常 SQL 失效:一次 DELETE USING 踩坑记录
java·后端
vibecoding日记13 小时前
双非如何快速入职字节等大厂大模型?真实案例分析:推理优化和投机解码
算法·求职·大模型工程师
yszaygr213815 小时前
Verilog参数化游程编码RLE模块
算法
SamDeepThinking15 小时前
从源码到代码:MyBatis-Flex 与 MyBatis-Plus 的逐项对比
java·后端·程序员
望易15 小时前
刚设计的大模型架构-双域耦合认知框架
算法·架构
她的男孩18 小时前
Spring Boot 接 Flowable 工作流:用 3 个注解搭一个请假审批流程
java·后端·架构
复杂网络19 小时前
多个 Claude Code 与多个 Codex 协同工作:设计与实现方案
算法
荣码20 小时前
LLM结构化输出:让AI返回JSON而不是废话,我踩了4个坑
java·python