【每日算法】LeetCode 234. 回文链表详解

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

LeetCode 234. 回文链表

1. 题目描述

给定一个单链表的头节点 head,请判断该链表是否为回文链表。如果是,返回 true;否则,返回 false

示例 1:

复制代码
输入: head = [1,2,2,1]
输出: true

示例 2:

复制代码
输入: head = [1,2]
输出: false

进阶要求: 尝试使用 O(n) 时间复杂度和 O(1) 空间复杂度解决此题。

2. 问题分析

回文链表是指链表节点值从前往后读和从后往前读完全一致。作为前端开发者,我们常处理类似 DOM 树或组件状态树的结构,链表作为一种线性数据结构,在内存管理和优化中具有参考价值。

核心挑战:

  • 链表单向遍历,无法直接反向访问。
  • 需要在有限空间内高效比较节点值。
  • 进阶要求 O(1) 空间,排除使用额外数组或栈等线性空间。

前端关联场景: 例如,在虚拟 DOM 差异算法或状态历史管理中,检查结构对称性可优化渲染性能。

3. 解题思路

3.1 思路一:转换为数组法

将链表值复制到数组,再用双指针从两端向中间比较回文。

  • 时间复杂度: O(n)
  • 空间复杂度: O(n)
  • 优点: 简单直观,易于实现。
  • 缺点: 额外 O(n) 空间,不满足进阶要求。

3.2 思路二:递归法

利用递归栈隐式存储节点,从链表两端向内比较。

  • 时间复杂度: O(n)
  • 空间复杂度: O(n)(递归调用栈)
  • 优点: 代码简洁,体现递归思想。
  • 缺点: 栈空间 O(n),可能栈溢出,不适合长链表。

3.3 思路三:快慢指针反转后半部分法(最优解)

使用快慢指针找到链表中点,反转后半部分链表,再比较前后两半是否一致。最后可选恢复链表。

  • 时间复杂度: O(n)
  • 空间复杂度: O(1)
  • 优点: 满足进阶要求,时间 O(n)、空间 O(1)。
  • 缺点: 修改链表结构,但可恢复。

4. 各思路代码实现

4.1 思路一:转换为数组法

javascript 复制代码
/**
 * Definition for singly-linked list.
 * function ListNode(val, next) {
 *     this.val = (val===undefined ? 0 : val)
 *     this.next = (next===undefined ? null : next)
 * }
 */
function isPalindrome(head) {
    const arr = [];
    let curr = head;
    while (curr !== null) {
        arr.push(curr.val);
        curr = curr.next;
    }
    let left = 0, right = arr.length - 1;
    while (left < right) {
        if (arr[left] !== arr[right]) return false;
        left++;
        right--;
    }
    return true;
}

4.2 思路二:递归法

javascript 复制代码
function isPalindrome(head) {
    let frontPointer = head;
    
    function recursivelyCheck(currentNode) {
        if (currentNode !== null) {
            if (!recursivelyCheck(currentNode.next)) return false;
            if (currentNode.val !== frontPointer.val) return false;
            frontPointer = frontPointer.next;
        }
        return true;
    }
    
    return recursivelyCheck(head);
}

4.3 思路三:快慢指针反转后半部分法

javascript 复制代码
function isPalindrome(head) {
    if (head === null || head.next === null) return true;
    
    // 快慢指针找中点
    let slow = head, fast = head;
    while (fast.next !== null && fast.next.next !== null) {
        slow = slow.next;
        fast = fast.next.next;
    }
    
    // 反转后半部分链表
    let secondHalfStart = reverseList(slow.next);
    
    // 比较前后两半
    let p1 = head, p2 = secondHalfStart;
    let isPal = true;
    while (p2 !== null) {
        if (p1.val !== p2.val) {
            isPal = false;
            break;
        }
        p1 = p1.next;
        p2 = p2.next;
    }
    
    // 恢复链表(可选,保持原结构)
    slow.next = reverseList(secondHalfStart);
    
    return isPal;
}

// 辅助函数:反转链表
function reverseList(head) {
    let prev = null, curr = head;
    while (curr !== null) {
        const nextTemp = curr.next;
        curr.next = prev;
        prev = curr;
        curr = nextTemp;
    }
    return prev;
}

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

思路 时间复杂度 空间复杂度 优点 缺点 适用场景
转换为数组法 O(n) O(n) 实现简单,快速原型开发 额外 O(n) 空间,不满足进阶要求 小规模数据或无需空间优化时
递归法 O(n) O(n) 代码简洁,递归思维训练 递归栈 O(n),可能栈溢出,性能较差 学习递归,链表长度有限时
快慢指针反转法 O(n) O(1) 最优解,空间高效,满足进阶要求 需要修改链表(可恢复),实现稍复杂 大规模数据、内存敏感场景

6. 总结

回文链表问题不仅是算法练习,更是前端开发者深化数据结构理解的契机。通过比较不同解法,我们学会在时间与空间之间权衡,这对前端性能优化至关重要。

实际应用场景:

  • 前端状态管理: 如 Redux 或 MobX 中,检查状态变更历史是否对称,以支持撤销/重做功能。
  • 虚拟 DOM 优化: 在 React 等框架中,比较组件树结构是否回文,可减少不必要的渲染。
  • 数据验证: 处理用户输入(如链表形式的嵌套配置)时,验证其对称性。
  • 内存敏感应用: 移动端或低端设备中,O(1) 空间算法能降低内存开销,提升应用流畅度。

作为前端开发者,掌握此类算法将助力你从实现功能转向设计高效系统,提升代码质量和问题解决能力。坚持每日算法练习,结合前端实践,你将在技术道路上走得更远。

相关推荐
汽车仪器仪表相关领域1 分钟前
NHXJ-02汽车悬架检验台 实操型实战手册
人工智能·功能测试·测试工具·算法·安全·单元测试·可用性测试
源码之屋2 分钟前
计算机毕业设计:Python天气数据采集与可视化分析平台 Django框架 线性回归 数据分析 大数据 机器学习 大模型 气象数据(建议收藏)✅
人工智能·python·深度学习·算法·django·线性回归·课程设计
我爱C编程3 分钟前
【3.2】FFT/IFFT变换的数学原理概述与MATLAB仿真
算法·matlab·fpga·fft·ifft
chao18984410 分钟前
基于改进二进制粒子群算法的含需求响应机组组合问题MATLAB实现
开发语言·算法·matlab
Imxyk18 分钟前
P9242 [蓝桥杯 2023 省 B] 接龙数列
c++·算法·图论
炽烈小老头21 分钟前
【每天学习一点算法 2026/04/10】Excel表列序号
学习·算法
郝学胜-神的一滴22 分钟前
二叉树后序遍历:从递归到非递归的优雅实现
数据结构·c++·程序人生·算法·
宝贝儿好24 分钟前
【LLM】第一章:分词算法BPE、WordPiece、Unigram、分词工具jieba
人工智能·python·深度学习·神经网络·算法·语言模型·自然语言处理
渡我白衣25 分钟前
运筹帷幄——在线学习与实时预测系统
人工智能·深度学习·神经网络·学习·算法·机器学习·caffe
colus_SEU26 分钟前
SVM 的终极视角:合页损失函数 (Hinge Loss) 与正则化
算法·机器学习·支持向量机