力扣刷题#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->left 和 root->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->right 是 nullptr,条件为假,不交换——但翻转 [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仅负责文本修饰,综合获得以上内容。

浙公网安备 33010602011771号