力扣刷题#28-0226-翻转二叉树

力扣刷题#28-0226-翻转二叉树

题目

给你一棵二叉树的根节点 root,翻转这棵二叉树,并返回其根节点。

输入: root = [4,2,7,1,3,6,9]
输出: [4,7,2,9,6,3,1]

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

我的思路

看到"翻转",直觉就是递归 + 交换——每个节点的左右孩子互换位置,然后递归处理子树。

生活化类比

照镜子。镜子里的树,每个节点的左右子树都互换了位置——整棵树以根节点为轴做镜像。


递归的四个步骤

步骤 做什么
① 出口 root 为空 → 返回 nullptr
② 交换 左右孩子互换位置
③ 递归 翻转新的左子树和新的右子树
④ 返回 返回 root

我的 AC 代码

class Solution {
public:
    TreeNode* invertTree(TreeNode* root) {
        if (root == nullptr) return nullptr;
        swap(root->left, root->right);
        invertTree(root->left);
        invertTree(root->right);
        return root;
    }
};

代码逐段解析

第 3 行:递归出口

if (root == nullptr) return nullptr;

空节点没有孩子可换,返回空。

第 4 行:交换左右孩子

swap(root->left, root->right);

std::swap 交换两个指针变量。不需要判断孩子是否为空——交换的是"位置",空位也是位置的一部分。

第 5-6 行:递归翻转子树

invertTree(root->left);
invertTree(root->right);

注意传的是 root->leftroot->right(交换后的),不是 root 自己——递归必须走向更小的子问题

第 7 行:返回根节点

return root;

翻转是在原树上就地修改的,根节点不变,返回它即可。


踩坑记录

坑 1:invertTree(root) 无限递归

// ❌ 第一版
if (root->right && root->left) invertTree(root);   // 传整个 root → 死循环

递归必须传更小的子树root->left / root->right),传 root 自己会无限循环爆栈。

坑 2:给交换加了"两个孩子都存在"的条件

// ❌
if (root->right && root->left) swap(root->left, root->right);

后果:测试用例 [1,2](根节点只有左孩子 2)失败。因为 root->rightnullptr,条件为假,不交换——但翻转 [1,2] 应该得到 [1,null,2](2 挪到右边)。

根因:翻转交换的是左右位置,空位(nullptr)也是位置的一部分。swap 对指针值(包括空指针)天然安全,不需要过滤:

原 left    原 right   swap 后 left  swap 后 right
节点2      nullptr    nullptr        节点2       ← [1,2] 正确翻转
节点4      节点5      节点5          节点4
nullptr    nullptr    nullptr        nullptr

复杂度分析

维度 说明
时间复杂度 O(n) 每个节点访问一次
空间复杂度 O(h) 递归栈深度 = 树高 h

关键点总结

关键点 说明
递归四步 出口 → 交换 → 递归子树 → 返回
交换对象 左右位置,空位也参与交换
递归参数 必须传子树,不能传 root 自己
就地翻转 原树修改,根节点不变

本文档由 AI 辅助生成,作者提供问题,思路和代码,AI仅负责文本修饰,综合获得以上内容。

posted @ 2026-08-07 08:23  STA_running  阅读(5)  评论(0)    收藏  举报