【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
函数纯度 ✅ 纯函数,无副作用 ❌ 有副作用
可重入性 ✅ 可重复调用 ❌ 原数据被改后无法恢复

结语:

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

相关推荐
独自破碎E2 小时前
机器人Java后端算法笔试题解析
java·windows·算法
我是一颗柠檬2 小时前
【JDK8新特性】函数式接口Day2
java·开发语言·后端·intellij-idea
Bat U2 小时前
JavaEE|JVM
java·jvm·java-ee
运筹vivo@2 小时前
3043. 最长公共前缀的长度(Leetcode 每日一题)
c++·算法·leetcode·职场和发展·每日一题
Mahir082 小时前
Spring Boot 自动装配深度解密:从原理到自定义 Starter 实战
java·spring boot·后端·自动装配·自定义starter·大厂面试题
淘源码d2 小时前
产科系统源码,数字产科源码,Java(后端) + Vue + ElementUI(前端) + MySQL(数据库),确保系统稳定性与扩展性。
java·源码·数字产科·产科系统·智能化孕产服务·高危五色预警·智慧产科
wand codemonkey3 小时前
SpringbootWeb【入门】+MySQL【安装】+【DataDrip安装 】+【连接MySQL】
java·mysql·mybatis
Mahir0811 小时前
Spring 循环依赖深度解密:从问题本质到三级缓存源码级解析
java·后端·spring·缓存·面试·循环依赖·三级缓存
RyFit12 小时前
SpringAI 常见问题及解决方案大全
java·ai