Skip to content

一、问题描述

翻转一棵二叉树。

示例:

输入:

     4
   /   \
  2     7
 / \   / \
1   3 6   9

输出:

     4
   /   \
  7     2
 / \   / \
9   6 3   1

二、方案一:递归法

1、思路

递归是解决树相关问题的常用方法。对于翻转二叉树,我们可以这样思考:

  • 交换每个节点的左右子节点。
  • 递归地对每个节点的左右子节点进行翻转。

2、代码实现

go
func invertTree(root *TreeNode) *TreeNode {
    if root == nil {
        return nil
    }
    // 交换左右子节点
    root.Left, root.Right = root.Right, root.Left
    // 递归翻转左右子树
    invertTree(root.Left)
    invertTree(root.Right)
    return root
}

3、复杂度分析

  • 时间复杂度:O(n),其中 n 是二叉树的节点数。我们只需要遍历每个节点一次。
  • 空间复杂度:O(n),在最坏的情况下,树完全不平衡,递归会调用 n 次(树的高度),因此需要 O(n) 的栈空间。

三、方案二:迭代法

1、思路

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

  • 使用队列存储每一层的节点。
  • 遍历队列中的每个节点,交换其左右子节点。
  • 将未访问的左右子节点加入队列。

2、代码实现

go
func invertTree(root *TreeNode) *TreeNode {
    if root == nil {
        return nil
    }
    queue := []*TreeNode{root}
    for len(queue) > 0 {
        // 取出当前节点
        cur := queue[0]
        queue = queue[1:]
        // 交换左右子节点
        cur.Left, cur.Right = cur.Right, cur.Left
        // 将左右子节点加入队列
        if cur.Left != nil {
            queue = append(queue, cur.Left)
        }
        if cur.Right != nil {
            queue = append(queue, cur.Right)
        }
    }
    return root
}

3、复杂度分析

  • 时间复杂度:O(n),其中 n 是二叉树的节点数。我们只需要遍历每个节点一次。
  • 空间复杂度:O(n),在最坏的情况下,树完全不平衡,队列中会包含所有节点,因此需要 O(n) 的空间。

四、总结

方案时间复杂度空间复杂度备注
递归法O(n)O(n)适用于所有类型的二叉树,代码简洁
迭代法O(n)O(n)需要额外的队列或栈空间,适用于所有类型的二叉树

两种方法在时间复杂度上相同,但在空间复杂度上,递归法由于使用系统栈可能会受到限制,而迭代法需要显式地分配队列空间。在实际应用中,可以根据具体情况选择合适的方法。

木川工作室 (微信:mcmc2024)