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;
}
相关推荐
wabs66642 分钟前
关于哈希表【力扣383.赎金信的思考】
算法·leetcode·散列表
love_muming1 小时前
二叉树操作全解析:从递归到层序遍历
java·数据结构·算法·二叉树
.道阻且长.10 小时前
2.LeetCode算法习题讲解--双指针--复写零
算法·leetcode·职场和发展
To_OC12 小时前
LC 438 找到所有字母异位词:暴力超时后,我靠滑动窗口一招搞定
javascript·算法·leetcode
Forever Nore14 小时前
学完C语言力扣第一题做不来正常吗
数据结构·算法
hansang_IR15 小时前
【题解】LC:倍增 / 区间并查集(Range Parallel Unionfind)
c++·算法·并查集
Tisfy16 小时前
LeetCode 3731.找出缺失的元素:哈希 / 排序
算法·leetcode·哈希算法·排序·哈希表
lucas_AI17 小时前
Q-CueGraph:你的多模态大模型会 zoom,但真的知道该看哪儿吗?
人工智能·算法
kaixin_啊啊17 小时前
test_机器学习算法学习
学习·算法·机器学习