【LeetCode热题100道笔记】回文链表

题目描述

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

示例 1:
在这里插入图片描述
输入:head = [1,2,2,1]
输出:true

示例 2:
在这里插入图片描述

输入:head = [1,2]
输出:false

提示:

  • 链表中节点数目在范围 [1,105][1, 10^5][1,105]
  • 0 <= Node.val <= 9

进阶:你能否用 O(n)O(n)O(n) 时间复杂度和 O(1)O(1)O(1) 空间复杂度解决此题?

思考

判断回文链表有两种典型思路,需根据「空间复杂度」需求选择,核心是利用回文“前后对称”的特性:

  1. 数组辅助法(O(n) 时间 + O(n) 空间)
    先遍历链表,将所有节点值存入数组,再用「相向双指针」(左指针从数组头部、右指针从数组尾部)逐位对比值是否相等。若全程相等则为回文,否则不是。
    优势是逻辑直观、实现简单;劣势是需额外存储数组,空间复杂度较高,不适用于内存敏感场景。

  2. 快慢指针+反转链表法(O(n) 时间 + O(1) 空间)
    这是满足「常数空间」的最优解,核心是用链表操作替代额外存储

    • 利用「快慢指针」找链表中点,将链表分为前半段和后半段;
    • 反转后半段链表,使后半段能“从后往前”与前半段对比;
    • 用「双指针」分别遍历前半段和反转后的后半段,逐位对比值;
    • (可选)对比结束后反转后半段并接回原链表,恢复链表结构。
      优势是无额外空间消耗,时间复杂度仍为 O(n);劣势是逻辑稍复杂,需处理链表反转和中点定位的边界。。

算法过程

  1. 找中点:初始化快慢指针均指向头节点,快指针每次走2步、慢指针每次走1步,直至快指针无法再走2步,此时慢指针指向前半段尾节点,后半段从慢指针.next开始;
  2. 反转后半段:迭代反转慢指针.next后的链表,得到反转后后半段的表头;
  3. 双指针对比:左指针从原链表头出发,右指针从反转后后半段表头出发,逐节点对比值,若不相等则非回文;
  4. 返回结果:若右指针遍历完仍未出现不相等,返回true(可选:反转后半段恢复原链表结构)。

代码

/**
 * Definition for singly-linked list.
 * function ListNode(val, next) {
 *     this.val = (val===undefined ? 0 : val)
 *     this.next = (next===undefined ? null : next)
 * }
 */
/**
 * @param {ListNode} head
 * @return {boolean}
 */
var isPalindrome = function(head) {
    if (!head.next) return true;

    let slow = head, fast = head;
   
    while (fast.next && fast.next.next) {
        slow = slow.next;
        fast = fast.next.next;
    }

    slow = reverseLink(slow.next);

    let node = head;
    while (slow) {
        if (node.val !== slow.val) return false;
        node = node.next;
        slow = slow.next;
    }


    return true;
};

function reverseLink(head) {
    if (!head) return head;
    let headNode = head;
    let node = head;
    while (node.next) {
        let tmp = node.next;
        node.next = tmp.next;
        tmp.next = headNode;
        headNode = tmp;
    }    
    return headNode;
}

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值