合并二叉树
问题描述:已知两颗二叉树,将它们合并成一颗二叉树。合并规则是:都存在的结点,就将节点值加起来,否则空的位置就由另一个树的节点来代替。例如:
两颗二叉树是:Tree 1
1
/ \
3 2
/
5
Tree 2
2
/ \
1 3
\ \
4 7
合并后的树为
3
/ \
4 5
/ \ \
5 4 7
示例1
输入:{1,3,2,5},{2,1,3,#,4,#,7}
返回值:{3,4,5,5,4,#,7}
方法一
思路分析
对二叉树的遍历还可通过层序遍历,即在层序遍历的过程中合并二叉树,此时需要使用一个辅助的数据结构,此处使用了队列,首先利用队列将两个二叉树根节点存储,然后队列弹出根节点相加,如果两个树的左节点均不为空,增将其放入队列,相应的如果两个树的右节点均不为空,增将其放入队列中,如果t1二叉树的左节点为空,t2左节点不为空,直接将t2的左节点赋予t1,同理右节点也如此,由此我们不断将子树放入队列,再从队列中取出节点,直到队列为空。层序遍历的核心思想是一层一层进行遍历。
动图详解
核心代码
import java.util.*; /* * public class TreeNode { * int val = 0; * TreeNode left = null; * TreeNode right = null; * } */ public class Solution { /** * * @param t1 TreeNode类 * @param t2 TreeNode类 * @return TreeNode类 */ public TreeNode mergeTrees (TreeNode t1, TreeNode t2) { // write code here if(t1==null || t2==null)//存在一个二叉树为空,则返回另一个二叉树 { return t1==null? t2 : t1; } LinkedList<TreeNode> linkedList = new LinkedList<>();//声明一个队列用于存储二叉树 linkedList.add(t1); linkedList.add(t2); while (!linkedList.isEmpty()){ TreeNode n1 = linkedList.poll();//弹出一个元素。根据不同的数据结构,结果也相应不同,此处为二叉树 TreeNode n2 = linkedList.poll(); n1.val = n1.val + n2.val; if (n1.left != null && n2.left != null)//两个数的左子树都不为空则将其放到列表中 { linkedList.add(n1.left); linkedList.add(n2.left); } else if (n1.left == null)//如果t1的左子树为空,将t2的左子树直接赋予t1 { n1.left = n2.left; } if (n1.right != null && n2.right != null)//两个数的右子树都不为空则将其放到列表中 { linkedList.add(n1.right); linkedList.add(n2.right); } else if (n1.right == null)////如果t1的右子树为空,将t2的右子树直接赋予t1 { n1.right = n2.right; } } return t1; } }
复杂度分析
- 时间复杂度:层序遍历时间复杂度为$O(N)$
- 空间复杂度:借助了一个辅助队列来存储二叉树节点,因此空间复杂度为$O(N)$
方法二
思路分析
我们已经知道对二叉树的访问有前序、中序、后序遍历三种基本的办法,那么我们可以想到可以使用前序遍历的方法对二叉树进行遍历,在遍历的过程中对两个二叉树的相应节点进行相加,这个过程可以用到递归方法,即树t1节点并且树t2的节点不为空时,合并两个节点的数值,递归合并两个树的左节点,递归合并两个树的右节点,如果树t1节点或者树t2的节点为空时,将树t2的节点赋值给t1,当两个数的节点都为空时,遍历完成,递归也就完成,此时t1即为合并后的二叉树。
动图详解
先进行根节点的合并,然后对左子树进行递归合并,之后对右子树递归合并,当两个树的节点均为空时,递归条件结束
JAVA 核心代码
import java.util.*; /* * public class TreeNode { * int val = 0; * TreeNode left = null; * TreeNode right = null; * } */ public class Solution { /** * * @param t1 TreeNode类 * @param t2 TreeNode类 * @return TreeNode类 */ public TreeNode mergeTrees (TreeNode t1, TreeNode t2) { // write code here if(t1 != null && t2 !=null)//递归中止的条件,树t1节点为空并且树t2的节点为空 { t1.val += t2.val;//将两个树的结点数值相加 t1.left = mergeTrees(t1.left, t2.left);//递归合并两个树的左节点 t1.right = mergeTrees(t1.right, t2.right);//递归合并两个数的右节点 } return t1 == null? t2 : t1; } }
复杂度分析
- 时间复杂度:递归的时间复杂度为递归的次数*每次递归中的操作次数,每次递归中的操作为一个加法操作,递归的次数为较小二叉树的节点数,因此时间复杂度为$O(min(t1,t2))$
- 空间复杂度:取决于递归调用的层数,递归调用的层数不会大于最小二叉树的高度,即空间复杂度$O(min(h1,h2))$,其中h1,h2分别为二叉树t1,t2的高度,最坏情况下二叉树的高度等于节点数