【每日算法】LeetCode 226. 翻转二叉树

对前端开发者而言,学习算法绝非为了"炫技"。它是你从"页面构建者"迈向"复杂系统设计者"的关键阶梯。它将你的编码能力从"实现功能"提升到"设计优雅、高效解决方案"的层面。从现在开始,每天投入一小段时间,结合前端场景去理解和练习,你将会感受到自身技术视野和问题解决能力的质的飞跃。------ 算法:资深前端开发者的进阶引擎

LeetCode 226. 翻转二叉树

1. 题目描述

LeetCode 226. 翻转二叉树要求我们翻转一棵二叉树,即交换每个节点的左右子树。这个问题看似简单,但它是理解递归和树遍历的经典入门题,对于前端开发者处理DOM树或组件树有直接借鉴意义。

示例

  • 输入:

    复制代码
       4
     /   \
    2     7

    / \ /
    1 3 6 9

  • 输出:

    复制代码
       4
     /   \
    7     2

    / \ /
    9 6 3 1

二叉树节点定义(在JavaScript中):

javascript 复制代码
function TreeNode(val, left, right) {
    this.val = (val===undefined ? 0 : val);
    this.left = (left===undefined ? null : left);
    this.right = (right===undefined ? null : right);
}

2. 问题分析

翻转二叉树的核心是遍历每个节点并交换其左右子节点。这涉及到二叉树的遍历,常见方法有递归和迭代。作为前端开发者,我们可以类比到DOM树的遍历或React/Vue组件树的处理,例如在UI中反转子组件顺序。

关键点:

  • 二叉树可能为空(根节点为null),需要处理边界情况。
  • 翻转是镜像操作,适用于任何二叉树结构(包括不平衡树)。
  • 时间复杂度与节点数相关,空间复杂度取决于遍历方式。

3. 解题思路

解决翻转二叉树主要有两种思路:递归和迭代。递归方法直观简洁,符合分治思想;迭代方法模拟递归过程,避免栈溢出风险。两种方法都是最优解,时间复杂度为O(n),其中n是节点数,因为每个节点访问一次。

  • 最优解:递归和迭代在时间复杂度上相同,但递归更简洁,易于理解;迭代在树深度大时更安全。前端场景中,递归适用于组件树递归渲染,迭代适用于性能敏感操作。

3.1 递归思路

从根节点开始,递归地翻转左子树和右子树,然后交换左右子节点。这类似于深度优先搜索(DFS)。

3.2 迭代思路

使用栈或队列模拟递归过程。栈实现深度优先遍历,队列实现广度优先遍历(BFS)。交换操作在遍历每个节点时进行。

4. 各思路代码实现

以下是基于JavaScript的代码实现,前端开发者可轻松集成到项目或算法练习中。

4.1 递归实现

递归方法直接模拟翻转过程,代码简洁。

javascript 复制代码
var invertTree = function(root) {
    // 基础情况:如果节点为空,直接返回
    if (root === null) {
        return null;
    }
    // 递归翻转左子树和右子树
    const left = invertTree(root.left);
    const right = invertTree(root.right);
    // 交换左右子节点
    root.left = right;
    root.right = left;
    return root;
};

4.2 迭代实现(使用栈)

迭代方法通过栈来模拟递归,避免递归调用栈溢出。

javascript 复制代码
var invertTree = function(root) {
    if (root === null) return null;
    const stack = [root]; // 使用栈存储节点
    while (stack.length > 0) {
        const node = stack.pop();
        // 交换当前节点的左右子节点
        [node.left, node.right] = [node.right, node.left];
        // 将子节点压入栈,继续处理
        if (node.left !== null) stack.push(node.left);
        if (node.right !== null) stack.push(node.right);
    }
    return root;
};

4.3 迭代实现(使用队列)

队列实现广度优先遍历,适合层次处理树。

javascript 复制代码
var invertTree = function(root) {
    if (root === null) return null;
    const queue = [root]; // 使用队列存储节点
    while (queue.length > 0) {
        const node = queue.shift();
        // 交换当前节点的左右子节点
        [node.left, node.right] = [node.right, node.left];
        // 将子节点加入队列
        if (node.left !== null) queue.push(node.left);
        if (node.right !== null) queue.push(node.right);
    }
    return root;
};

5. 各实现思路的复杂度、优缺点对比表格

以下表格总结了不同实现方式的性能特点和适用场景,帮助前端开发者根据实际需求选择。

实现方式 时间复杂度 空间复杂度 优点 缺点 前端应用场景
递归 O(n) O(h),其中h是树高,最坏情况O(n) 代码简洁,易于理解和实现;符合函数式编程思想 递归深度大时可能导致栈溢出;调试可能较复杂 处理嵌套组件树、递归渲染UI(如React递归组件)
迭代(栈) O(n) O(n),栈存储节点 避免递归栈溢出;控制流清晰,适合深度遍历 需要额外空间;代码稍复杂 DOM树深度遍历、状态管理中的树操作
迭代(队列) O(n) O(n),队列存储节点 层次遍历,适合广度优先处理;避免栈溢出 空间开销可能较大;交换顺序可能影响性能 UI布局反转、层级数据处理(如树形菜单)
  • 时间复杂度:所有方法都是O(n),因为每个节点访问一次。
  • 空间复杂度:递归为O(h),取决于树高;迭代为O(n),在最坏情况下存储所有节点。
  • 最优解选择:对于大多数前端场景,递归是首选,因为代码可读性高;在树深度未知或较大时,迭代更安全。
相关推荐
野生技术架构师18 分钟前
2026 Java 面试全套总结,八股 + 场景 + AI 相关面试考点
java·人工智能·面试
mmmmath_32 小时前
LeetCode.541.反转字符串II
数据结构·算法·leetcode
Navigator_Z2 小时前
LeetCode //MySQL - 1251. Average Selling Price
c语言·算法·leetcode
Captaincc2 小时前
AI用量v0.1.11更新发布 新增 jusage doctor 诊断指令 托盘展示token 和余额 新增 AutoClaw 支持
前端·后端·vibecoding
醇氧3 小时前
MySQL 8.0 系统表损坏与引擎转换故障排查实战
数据结构·算法
大熊背3 小时前
《Color constancy by characterization of illumination chromaticity》之色度色域最大化算法(二)
算法·白平衡·色度·色温
钓鱼的肝3 小时前
梳理(1-5)
c++·经验分享·笔记·算法·青少年编程
参.商.4 小时前
【Day 53】76. 最小覆盖子串
leetcode·golang
HZZD_HZZD4 小时前
CSDN_批发市场水电漏损归因算法LAM的原理与落地
嵌入式硬件·物联网·算法