226. 翻转二叉树

给你一棵二叉树的根节点 root ,翻转这棵二叉树,并返回其根节点。我们可以使用递归的方式来解决这个问题,也可以用迭代(BFS 或 DFS)实现,但递归是最简洁直观的方式。

解题思路

我们可以使用 递归 的方式来解决这个问题:

  • 如果当前节点为空,直接返回 null。
  • 否则,递归地翻转左子树和右子树。
  • 然后交换当前节点的左右子节点。
  • 最后返回当前节点(即翻转后的根)。

也可以用 迭代(BFS 或 DFS) 实现,但递归是最简洁直观的方式。


Java 代码实现(递归)

// Definition for a binary tree node.
class TreeNode {
    int val;
    TreeNode left;
    TreeNode right;
    TreeNode() {}
    TreeNode(int val) { this.val = val; }
    TreeNode(int val, TreeNode left, TreeNode right) {
        this.val = val;
        this.left = left;
        this.right = right;
    }
}

public class Solution {
    public TreeNode invertTree(TreeNode root) {
        // 基本情况:如果节点为空,直接返回
        if (root == null) {
            return null;
        }

        // 递归翻转左右子树
        TreeNode left = invertTree(root.left);
        TreeNode right = invertTree(root.right);

        // 交换左右子树
        root.left = right;
        root.right = left;

        return root;
    }
}

示例

输入:

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

输出:

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

时间复杂度 & 空间复杂度

  • 时间复杂度:O(n),其中 n 是树中节点的个数,每个节点都会被访问一次。
  • 空间复杂度:O(h),其中 h 是树的高度,主要是递归调用栈的深度。最坏情况下(退化为链表)为 O(n),最好情况下(完全平衡)为 O(log n)。

下面是 迭代版本 的「翻转二叉树」实现。我们可以使用 栈(DFS)队列(BFS) 来遍历所有节点,并在访问每个节点时交换它的左右子节点。


方法一:使用栈(模拟 DFS)

import java.util.*;

public class Solution {
    public TreeNode invertTree(TreeNode root) {
        if (root == null) {
            return null;
        }

        Stack<TreeNode> stack = new Stack<>();
        stack.push(root);

        while (!stack.isEmpty()) {
            TreeNode node = stack.pop();

            // 交换左右子节点
            TreeNode temp = node.left;
            node.left = node.right;
            node.right = temp;

            // 将非空子节点压入栈(顺序无所谓,因为只是遍历)
            if (node.left != null) {
                stack.push(node.left);
            }
            if (node.right != null) {
                stack.push(node.right);
            }
        }

        return root;
    }
}

方法二:使用队列(BFS,层序遍历)

import java.util.*;

public class Solution {
    public TreeNode invertTree(TreeNode root) {
        if (root == null) {
            return null;
        }

        Queue<TreeNode> queue = new LinkedList<>();
        queue.offer(root);

        while (!queue.isEmpty()) {
            TreeNode node = queue.poll();

            // 交换左右子节点
            TreeNode temp = node.left;
            node.left = node.right;
            node.right = temp;

            // 将非空子节点加入队列
            if (node.left != null) {
                queue.offer(node.left);
            }
            if (node.right != null) {
                queue.offer(node.right);
            }
        }

        return root;
    }
}

说明

  • 两种迭代方法本质相同:遍历所有节点 + 交换左右孩子
  • 区别仅在于遍历顺序:
    • 栈 → 深度优先(先处理子树深处)
    • 队列 → 广度优先(一层一层处理)
  • 实际效果一样,最终整棵树都会被翻转。

复杂度分析(迭代版)

  • 时间复杂度:O(n),每个节点访问一次。
  • 空间复杂度:O(w),其中 w 是树的最大宽度(队列或栈的最大大小)。
    • 最坏情况(完全二叉树底层满):O(n)
    • 平均情况:O(n/2) ≈ O(n)

本站简介

聚焦于全栈技术和量化技术的技术博客,分享软件架构、前后端技术、量化技术、人工智能、大模型等相关文章总结。