「这是我参与11月更文挑战的第 28 天,活动详情查看:2021最后一次更文挑战」
刷算法题,从来不是为了记题,而是练习把实际的问题抽象成具体的数据结构或算法模型,然后利用对应的数据结构或算法模型来进行解题。个人觉得,带着这种思维刷题,不仅能解决面试问题,也能更多的学会在日常工作中思考,如何将实际的场景抽象成相应的算法模型,从而提高代码的质量和性能
合并二叉树
题目来源:LeetCode-617. 合并二叉树
题目描述
给定两个二叉树,想象当你将它们中的一个覆盖到另一个上时,两个二叉树的一些节点便会重叠
你需要将他们合并为一个新的二叉树。合并的规则是如果两个节点重叠,那么将他们的值相加作为节点合并后的新值,否则不为 NULL 的节点将直接作为新二叉树的节点
示例
输入
输入:
Tree 1 Tree 2
1 2
/ \ / \
3 2 1 3
/ \ \
5 4 7
输出
合并后的树:
3
/ \
4 5
/ \ \
5 4 7
提示:
- 合并必须从两个树的根节点开始
解题
解法一:递归(前序遍历)
思路
这道题还是相当简单的,要合并二叉树,首先想到的就是分别遍历两棵树,然后按照题目中的合并规则进行合并
题目提示从根节点开始合并,那就应该想到前序遍历,只有前序遍历是从根开始打印的。要合并两个树,一个节点一个节点的合并即可。首先根据上边的合并规则,我们可以得到以下信息
- 当两个节点都为空的时候,那就返回空
- 当两个节点有一个为空的时候,就返回另外一个节点
- 当两个节点都不为空的时候,去这两个节点值的和
有了上边的思路,翻译成代码就简单了
本题也可以用广度优先搜索,只不过实现起来较为麻烦,需要借助三个队列,能搞明白前序遍历这种方法就差不多了。如果感兴趣,可以试着用广度优先搜索实现一下
关于树的递归,千万别像计算机那样,顺序的去过每一个步骤,计算机擅长这种深度重复的事情,但是人脑不行,递归一旦深了,就容易乱,你可以假设直接拿到了递归的结果。比如下边代码中,root1.Left = mergeTrees(root1.Left, root2.Left),你不用脑子里边去想mergeTrees这个方法里边完整的执行过程,你就假设拿到了这个函数的执行结果,它的执行结果,无非就是上边列的三种情况,你就假设拿到了其中的任何一种情况的结果,这样理解起来就简单很多。关于递归,我之前做过详细的总结,感兴趣的可以看看
代码
//合并二叉树
func mergeTrees(root1 *TreeNode, root2 *TreeNode) *TreeNode {
if root1 == nil {
return root2
}
if root2 == nil {
return root1
}
root1.Val = root1.Val + root2.Val
root1.Left = mergeTrees(root1.Left, root2.Left)
root1.Right = mergeTrees(root1.Right, root2.Right)
return root1
}