给定两个二叉树,想象当你将它们中的一个覆盖到另一个上时,两个二叉树的一些节点便会重叠。
你需要将他们合并为一个新的二叉树。合并的规则是如果两个节点重叠,那么将他们的值相加作为节点合并后的新值,否则不为 NULL 的节点将直接作为新二叉树的节点。
示例 1:
注意: 合并必须从两个树的根节点开始。
思路:
如何同时遍历两个二叉树?
其实和遍历一个树的逻辑是一样的,只不过传入两个树的节点,同时操作。
1. 确定递归函数的参数和返回值
要合并两个二叉树,参数要穿入两个二叉树的根节点,返回值就是合并之后二叉树的根节点。
2. 确定终止条件
终止条件:
传入了两个树,有两个树遍历的节点t1和t2。
如果t1为None,两个树合并就是t2(如果t2也是None也没关系,那合并之后就是None)
反之,如果t2为None,那两个树合并就是t1(如果t1也是None也没关系,那合并之后就是None)
3. 确定单层递归的逻辑
在单层递归中,把两棵树的元素加到一起。
# Definition for a binary tree node.
class TreeNode:
def __init__(self, val=0, left=None, right=None):
self.val = val
self.left = left
self.right = right
class Solution:
def mergeTrees(self, root1: TreeNode, root2: TreeNode) -> TreeNode:
# 如果两个节点都为空,返回空
if not root1 and not root2:
return None
# 如果一个节点为空,返回另一个节点
if not root1:
return root2
if not root2:
return root1
# 合并两个节点的值
merged = TreeNode(root1.val + root2.val)
# 递归合并左子树
merged.left = self.mergeTrees(root1.left, root2.left)
# 递归合并右子树
merged.right = self.mergeTrees(root1.right, root2.right)
return merged
这个代码在处理其中一个树节点为空时,已经能够很好地处理树的合并。当一个树的节点为空,而另一个树的节点不为空时,代码会返回非空的那个节点及其子树。因此,无论这个非空节点下面是否有很长的子树,代码都可以正确处理。这里是原理解释:
- 如果
root1
为空且root2
不为空,代码返回root2
,因此root2
及其所有子节点都会被保留下来。 - 如果
root2
为空且root1
不为空,代码返回root1
,因此root1
及其所有子节点都会被保留下来。
这保证了非空树的结构和子树在合并后的树中都能被保留。
也可以写成这样:
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, val=0, left=None, right=None):
# self.val = val
# self.left = left
# self.right = right
class Solution:
def mergeTrees(self, root1: TreeNode, root2: TreeNode) -> TreeNode:
# 递归终止条件:
# 但凡有一个节点为空, 就立刻返回另外一个. 如果另外一个也为None就直接返回None.
if not root1:
return root2
if not root2:
return root1
# 上面的递归终止条件保证了代码执行到这里root1, root2都非空.
root1.val += root2.val # 中
root1.left = self.mergeTrees(root1.left, root2.left) #左
root1.right = self.mergeTrees(root1.right, root2.right) # 右
return root1 # ⚠️ 注意: 本题我们重复使用了题目给出的节点而不是创建新节点. 节省时间, 空间.