Skip to content

一、问题描述

给定两个二叉树,想象当你将它们中的一个覆盖到另一个上时,两个二叉树的一些节点会重叠。你需要将他们合并为一个新的二叉树。合并的规则是如果两个节点重叠,那么将他们的值相加作为节点合并后的新值,否则不为 NULL 的节点将直接作为新二叉树的节点。

二、方案一:递归法

1、思路

递归是解决树相关问题的常用方法。对于这个问题,我们可以递归地合并两个树的节点。

  • 如果两个节点都为空,返回空。
  • 如果一个节点为空,返回另一个节点。
  • 如果两个节点都不为空,创建一个新的节点,其值为两个节点值之和,然后递归地合并左右子树。

2、代码实现

go
func mergeTrees(root1 *TreeNode, root2 *TreeNode) *TreeNode {
    if root1 == nil {
        return root2
    }
    if root2 == nil {
        return root1
    }
    root1.Val += root2.Val
    root1.Left = mergeTrees(root1.Left, root2.Left)
    root1.Right = mergeTrees(root1.Right, root2.Right)
    return root1
}

3、复杂度分析

  • 时间复杂度:O(min(m, n)),其中m和n分别是两个树的节点数。
  • 空间复杂度:O(min(m, n)),递归栈的深度取决于两个树中较小的一个。

三、方案二:迭代法

1、思路

迭代法通常使用栈或队列来模拟递归过程。

  • 使用队列来存储待合并的节点对。
  • 遍历队列,对于每一对节点,执行合并操作。
  • 如果两个节点都不为空,将它们的值相加,并将非空的左右子节点加入队列。

2、代码实现

go
func mergeTrees(root1 *TreeNode, root2 *TreeNode) *TreeNode {
    if root1 == nil {
        return root2
    }
    queue := []*TreeNode{root1, root2}
    for len(queue) > 0 {
        node1, node2 := queue[0], queue[1]
        queue = queue[2:]
        if node2 == nil {
            continue
        }
        node1.Val += node2.Val
        if node1.Left == nil {
            node1.Left = node2.Left
        } else {
            queue = append(queue, node1.Left, node2.Left)
        }
        if node1.Right == nil {
            node1.Right = node2.Right
        } else {
            queue = append(queue, node1.Right, node2.Right)
        }
    }
    return root1
}

3、复杂度分析

  • 时间复杂度:O(min(m, n)),其中m和n分别是两个树的节点数。
  • 空间复杂度:O(min(m, n)),队列中最多包含两个树中较小的一个的所有节点。

四、总结

递归法和迭代法都能有效地解决这个问题。递归法代码更简洁,但迭代法在空间复杂度上可能更有优势,因为它不需要递归栈空间。具体使用哪种方法取决于个人偏好和具体问题的需求。

木川工作室 (微信:mcmc2024)