高频算法面试题(四十三)- 合并二叉树

256 阅读3分钟

「这是我参与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
}