617. 合并二叉树

617. 合并二叉树

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] 内
  • -10^4 <= Node.val <= 10^4

思路

相信这道题目很多同学疑惑的点是如何同时遍历两个二叉树呢?

其实和遍历一个树逻辑是一样的,只不过传入两个树的节点,同时操作。

递归

二叉树使用递归,就要想使用前中后哪种遍历方式?

构造树一般都会用前序遍历,先构造根节点,然后递归构造根节点的左右子树。

那么我们来按照递归三部曲来解决:

  1. 确定递归函数的参数和返回值:
    首先要合入两个二叉树,那么参数至少是要传入两个二叉树的根节点,返回值就是合并之后二叉树的根节点。发现和题目给的函数参数与返回值都一致,故不用新定义dfs辅助函数了。

代码如下:

func mergeTrees(root1 *TreeNode, root2 *TreeNode) *TreeNode {}
  1. 确定终止条件:
    因为是传入了两个树,那么就有两个树遍历的节点root1root2,如果root1 == nil 了,两个树合并就应该是 root2 了(如果root2也为nil也无所谓,合并之后就是nil)。

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

代码如下:

if root1 == nil { // 如果root1为空,合并之后就应该是root2
  	return root2
 }
 if root2 == nil {// 如果root2为空,合并之后就应该是root1
    return root1
 }
  1. 确定单层递归的逻辑:
    单层递归的逻辑就比较好写了,这里我们重复利用一下root1这个树,root1就是合并之后树的根节点(就是修改了原来树的结构)。

那么单层递归中,就要把两棵树的元素加到一起。

root1.Val = root1.Val + root2.Val // 复用一下,将root1作为结果树

接下来构造左右子树

  • root1 的左子树是:合并 root1左子树 root2左子树之后的左子树。

  • root1 的右子树是:是 合并 root1右子树 root2右子树之后的右子树。

最终root1就是合并之后的根节点。

代码如下:

root1.Left = mergeTrees(root1.Left,root2.Left)
root1.Right = mergeTrees(root1.Right,root2.Right)
return root1

此时前序遍历,完整代码就写出来了,如下:

/**
 * Definition for a binary tree node.
 * type TreeNode struct {
 *     Val int
 *     Left *TreeNode
 *     Right *TreeNode
 * }
 */
func mergeTrees(root1 *TreeNode, root2 *TreeNode) *TreeNode {
    // 如果root1是nil,则不管root2是否为空,都可以直接返回root2
    // 反之,如果root2是空,则可以直接返回root1
    // 如果root1和root2都不为空,则数值相加作为新节点的值,继续递归构造左右子树
    if root1 == nil {
        return root2
    }
    if root2 == nil {
        return root1
    }

    root1.Val = root1.Val + root2.Val // 复用一下,将root1作为结果树
    root1.Left = mergeTrees(root1.Left,root2.Left)
    root1.Right = mergeTrees(root1.Right,root2.Right)

    return root1
}

在这里插入图片描述

如上的方法修改了root1的结构,当然也可以不修改root1root2的结构,重新定义一个树。

不修改输入树的结构,前序遍历,代码如下:

/**
 * Definition for a binary tree node.
 * type TreeNode struct {
 *     Val int
 *     Left *TreeNode
 *     Right *TreeNode
 * }
 */
func mergeTrees(root1 *TreeNode, root2 *TreeNode) *TreeNode {
    // 如果root1是nil,则不管root2是否为空,都可以直接返回root2
    // 反之,如果root2是空,则可以直接返回root1
    // 如果root1和root2都不为空,则数值相加作为新节点的值,继续递归构造左右子树
    if root1 == nil {
        return root2
    }
    if root2 == nil {
        return root1
    }

    root := &TreeNode{Val:root1.Val + root2.Val}
    root.Left = mergeTrees(root1.Left,root2.Left)
    root.Right = mergeTrees(root1.Right,root2.Right)

    return root
}

总结

合并二叉树,也是二叉树操作的经典题目,如果没有接触过的话,其实并不简单,因为我们习惯了操作一个二叉树,一起操作两个二叉树,还会有点懵懵的。

迭代法中,一般一起操作两个树都是使用队列模拟类似层序遍历,同时处理两个树的节点,这种方式最好理解,如果用模拟递归的思路的话,要复杂一些。

实现如下: ```c #include <stdio.h> #include <stdlib.h> struct TreeNode { int val; struct TreeNode *left; struct TreeNode *right; }; struct TreeNode* mergeTrees(struct TreeNode* t1, struct TreeNode* t2) { if (t1 == NULL) return t2; if (t2 == NULL) return t1; t1->val += t2->val; t1->left = mergeTrees(t1->left, t2->left); t1->right = mergeTrees(t1->right, t2->right); return t1; } int main() { // 构造两棵树 struct TreeNode *t1 = (struct TreeNode*)malloc(sizeof(struct TreeNode)); struct TreeNode *t2 = (struct TreeNode*)malloc(sizeof(struct TreeNode)); t1->val = 1; t1->left = (struct TreeNode*)malloc(sizeof(struct TreeNode)); t1->left->val = 3; t1->left->left = (struct TreeNode*)malloc(sizeof(struct TreeNode)); t1->left->left->val = 5; t1->left->left->left = NULL; t1->left->left->right = NULL; t1->left->right = NULL; t1->right = (struct TreeNode*)malloc(sizeof(struct TreeNode)); t1->right->val = 2; t1->right->left = NULL; t1->right->right = NULL; t2->val = 2; t2->left = (struct TreeNode*)malloc(sizeof(struct TreeNode)); t2->left->val = 1; t2->left->left = NULL; t2->left->right = (struct TreeNode*)malloc(sizeof(struct TreeNode)); t2->left->right->val = 4; t2->left->right->left = NULL; t2->left->right->right = NULL; t2->right = (struct TreeNode*)malloc(sizeof(struct TreeNode)); t2->right->val = 3; t2->right->left = NULL; t2->right->right = (struct TreeNode*)malloc(sizeof(struct TreeNode)); t2->right->right->val = 7; t2->right->right->left = NULL; t2->right->right->right = NULL; // 合并两棵树 struct TreeNode *t = mergeTrees(t1, t2); // 输出合并后的树 printf("%d\n", t->val); printf("%d %d\n", t->left->val, t->right->val); printf("%d %d %d %d\n", t->left->left->val, t->left->right->val, t->right->left->val, t->right->right->val); return 0; } ``` 该程序的输出结果为: ``` 3 4 5 5 4 7 0 ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值