

🔥个人主页:北极的代码(欢迎来访)
🎬作者简介:java后端学习者
✨命运的结局尽可永在,不屈的挑战却不可须臾或缺!
前言:
大家好,我是代码不加冰,在这里先祝大家周末愉快!然后来到我们每日刷题的环节,嗯,在此之前我都是想着上午刷题,然后顺带着把文章发了,但是每次上午都有课,然后有时候还起不来,所以每次都拖到了下午甚至晚上,如果有时间还是每天多刷几题,感觉进度有点慢了,效率不是很高。
摘要:
本文介绍了合并两棵二叉树的两种方法:原地修改法和新建树法。原地修改法直接在root1上进行节点值相加,节省空间但会破坏原树结构;新建树法则创建全新节点,保留原树但消耗更多内存。两种方法均采用深度优先搜索递归实现,时间复杂度均为O(min(m,n))。文章通过代码对比和优缺点分析,帮助开发者根据实际需求选择合适方案,强调了在内存敏感场景下原地修改的优势,以及在需要保留原树时的新建树方案。
题目背景:617.合并二叉树
给你两棵二叉树:
root1和root2。想象一下,当你将其中一棵覆盖到另一棵之上时,两棵树上的一些节点将会重叠(而另一些不会)。你需要将这两棵树合并成一棵新二叉树。合并的规则是:如果两个节点重叠,那么将这两个节点的值相加作为合并后节点的新值;否则,不为 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 |
| 函数纯度 | ✅ 纯函数,无副作用 | ❌ 有副作用 |
| 可重入性 | ✅ 可重复调用 | ❌ 原数据被改后无法恢复 |
结语:
如果对你有帮助,请**点赞,关注,收藏,**你的支持就是我最大的鼓励!
