LeetCode 226. 翻转二叉树

LeetCode 226. 翻转二叉树

摘要

LeetCode 226 翻转二叉树题解,使用迭代法(栈)前序遍历实现二叉树翻转,时间复杂度 O(n),空间复杂度 O(n)。本文同时讨论前序、后序遍历可行而中序遍历不可行的原因。

标签

#算法 #LeetCode #二叉树 #栈 #迭代 #题解

目录

  1. 题目描述

  2. 易错点

  3. 思路

    • 前序遍历可行
    • 后序遍历可行
    • 中序遍历陷阱
  4. 编写代码


1. 题目描述

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

示例 1:

text

ini 复制代码
输入:root = [4,2,7,1,3,6,9]
输出:[4,7,2,9,6,3,1]

示例 2:

text

ini 复制代码
输入:root = [2,1,3]
输出:[2,3,1]

示例 3:

text

ini 复制代码
输入:root = []
输出:[]

提示:

  • 树中节点数目范围是 [0, 100]
  • -100 <= Node.val <= 100

2. 易错点

  1. 空树直接返回 NULL
  2. 翻转时需交换左右子树的指针,注意使用临时变量保存。
  3. 迭代法中,栈存储节点指针,访问顺序需符合遍历要求。
  4. 释放动态分配的栈内存,避免内存泄漏。
  5. 中序遍历无法正确翻转,需避免使用。

3. 思路

翻转二叉树的本质是交换每个节点的左右子树。任何遍历顺序只要能保证每个节点的左右子树都被交换且不重复、不遗漏即可。但不同遍历顺序的效果不同。

前序遍历可行

前序遍历顺序:根 → 左 → 右

  • 访问根节点时,交换其左右子树。
  • 然后遍历左子树(此时左子树已经是原右子树,但尚未被处理),再遍历右子树(原左子树)。
  • 由于每个节点在其子节点被处理之前就已经完成了交换,子节点指针已经正确指向新的子树,因此后续遍历会正确处理所有节点。
  • 每个节点恰好被交换一次。

后序遍历可行

后序遍历顺序:左 → 右 → 根

  • 先递归处理左子树和右子树,使它们自身完成翻转。
  • 然后交换当前节点的左右子树。
  • 这样每个节点也只被交换一次,且子树的翻转在交换前完成,逻辑正确。

中序遍历陷阱

中序遍历顺序:左 → 根 → 右

  • 假设当前节点为 root,先遍历左子树(root->left)。
  • 然后访问 root,交换 root->leftroot->right
  • 此时 root->right 变成了原来的左子树(已经被遍历过),而 root->left 变成了原来的右子树(尚未被遍历)。
  • 接着中序遍历会去遍历右子树,也就是 root->right(注意此时 root->right 已经是原来的左子树),但该子树已经在前面的步骤中被完整遍历过了。
  • 而原来的右子树(现在变成了 root->left)却永远不会被遍历,因为中序遍历已经经过了左子树(在交换前),现在不会再回头。
  • 结果就是:原来左子树被翻转了两次(一次在遍历时,一次在作为右子树被处理时?实际上它是被重复遍历了但未被正确翻转),而原来的右子树完全没有被翻转。

具体过程示例(以节点 2 为根,左子树 1,右子树 3):

  1. 中序递归:先处理左子树 1(无子节点,返回)。
  2. 访问根 2,交换左右 -> 左=3,右=1。
  3. 然后中序遍历右子树,即 node->right = 1,但 1 已经被处理过了(且已返回),不会再次翻转。
  4. 结果是节点 3 从未被处理,因此 3 的子树(如果有)不会被翻转。

所以中序遍历在翻转二叉树时会导致部分节点被遗漏或重复处理,无法得到正确结果。因此,通常采用前序或后序遍历。


4. 编写代码

采用前序遍历迭代法(栈实现):

c 运行

c

ini 复制代码
struct TreeNode* invertTree(struct TreeNode* root) {
    if (root == NULL) return NULL;

    struct TreeNode** stack = (struct TreeNode**)malloc(10000 * sizeof(struct TreeNode*));
    int top = 0;
    stack[top++] = root;

    while (top > 0) {
        struct TreeNode* node = stack[--top];
        struct TreeNode* temp = node->left;
        node->left = node->right;
        node->right = temp;
        if (node->left)  stack[top++] = node->left;
        if (node->right) stack[top++] = node->right;
    }

    free(stack);
    return root;
}
相关推荐
剑锋所指,所向披靡!18 小时前
数据结构之关键路径
数据结构·算法
阿宇的技术日志18 小时前
漏桶、令牌桶、滑动窗口 三限流算法理解
算法·滑动窗口·漏桶·令牌桶
来一碗刘肉面19 小时前
队列的链式实现
数据结构·c++·算法·链表
KaMeidebaby19 小时前
卡梅德生物技术快报|原核膜蛋白表达优化实操手册,膜蛋白的纯化梯度洗脱完整流程
前端·网络·数据库·人工智能·算法
naturerun19 小时前
逐步插入回路法构造欧拉回路的算法
c++·算法
qizayaoshuap19 小时前
# [特殊字符] 骰子模拟器 — 鸿蒙ArkTS随机算法与动画系统设计
算法·华为·harmonyos
山顶夕景19 小时前
【DWT】计算两不等序列相似度:DWT
算法·动态规划·检索·模式识别·相似度
奶人五毛拉人一块20 小时前
二分算法以及习题讲解
数据结构·算法·二分
兰令水20 小时前
hot100【acm版】【2026.7.19打卡-java版本】
java·数据结构·算法·leetcode·面试