一起学习LeetCode热题100道(24/100)

24.回文链表(学习)

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

示例 1:

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

输出:true

示例 2:

输入:head = [1,2]

输出:false

提示:

链表中节点数目在范围[1, 105] 内

0 <= Node.val <= 9

解析:
一、找到链表的中点

1.初始化两个指针 slow 和 fast,都指向链表的头节点 head。

2.进入循环,条件为 fast 和 fast.next 都不为 null(确保 fast 可以安全地移动两步)。

3.在循环内部,slow 指针每次向前移动一步(slow = slow.next),fast 指针每次向前移动两步(fast = fast.next.next)。

4.当循环结束时,slow 指针要么指向链表的中点(如果链表长度是偶数),要么指向中间两个节点的第一个(如果链表长度是奇数)。

二、反转链表的后半部分

1.从 slow 指针开始反转链表。注意,如果链表长度是奇数,我们实际上是从 slow.next 开始反转的,因为 slow 已经是指向中间节点的指针了。

2.使用三个指针 prev(初始化为 null),curr(初始化为 slow 或 slow.next,取决于链表长度是否为奇数),和 nextTemp 来反转链表。

3.在循环中,将 curr.next 保存到 nextTemp,然后将 curr.next 指向 prev,接着将 prev 向前移动到 curr,最后将 curr 向前移动到 nextTemp。

4.循环继续,直到 curr 为 null。此时,prev 就是反转后的链表的头节点。

三、比较前半部分和反转后的后半部分

1.初始化两个指针 p1 和 p2,分别指向原链表的头节点 head 和反转后的链表的头节点 prev。

2.进入循环,条件为 p2 不为 null(确保我们可以安全地遍历反转后的链表的后半部分)。

3.在循环内部,比较 p1.val 和 p2.val。如果它们不相等,则返回 false,因为链表不是回文的。

4.如果它们相等,则将 p1 和 p2 都向前移动一步(p1 = p1.next 和 p2 = p2.next)。

5.循环结束后,如果没有提前返回 false,则说明链表是回文的,返回 true。

javascript 复制代码
var isPalindrome = function(head) {
     if (!head || !head.next) return true;  
  
    let slow = head;  
    let fast = head;  
    let prevPtr = null;  
  
    // 使用快慢指针找到中点  
    while (fast && fast.next) {  
        prevPtr = slow;  
        slow = slow.next;  
        fast = fast.next.next;  
    }  
  
    // 如果链表长度为奇数,则跳过中点  
    if (fast) {  
        slow = slow.next;  
    }  
  
    // 反转链表的后半部分  
    let secondHalf = reverseList(slow);  
  
    // 比较前半部分和反转后的后半部分  
    let p1 = head;  
    let p2 = secondHalf;  
    while (p2) {  
        if (p1.val !== p2.val) {  
            return false;  
        }  
        p1 = p1.next;  
        p2 = p2.next;  
    }  
  
    // 如果需要,可以在这里恢复链表(可选)  
  
    return true; 
};

function reverseList(head) {  
    let prev = null;  
    let curr = head;  
    while (curr) {  
        let nextTemp = curr.next;  
        curr.next = prev;  
        prev = curr;  
        curr = nextTemp;  
    }  
    return prev; // 新的头节点  
}  
相关推荐
B612 little star king几秒前
力扣29. 两数相除题解
java·算法·leetcode
野犬寒鸦1 分钟前
力扣hot100:环形链表(快慢指针法)(141)
java·数据结构·算法·leetcode·面试·职场和发展
时光追逐者6 分钟前
C# 哈希查找算法实操
算法·c#·哈希算法
Jasmine_llq30 分钟前
《P3825 [NOI2017] 游戏》
算法·游戏·枚举法·2-sat 算法·tarjan 算法·邻接表存储
Miraitowa_cheems34 分钟前
LeetCode算法日记 - Day 38: 二叉树的锯齿形层序遍历、二叉树最大宽度
java·linux·运维·算法·leetcode·链表·职场和发展
wangzy198234 分钟前
图形基础算法:如何将点与带曲线边的多边形位置关系算法做稳定
算法
艾醒1 小时前
探索大语言模型(LLM):Ollama快速安装部署及使用(含Linux环境下离线安装)
人工智能·深度学习·算法
艾醒1 小时前
探索大语言模型(LLM):Open-WebUI的安装
人工智能·算法·全栈
时空自由民.1 小时前
repo 学习教程
大数据·学习·elasticsearch
猫天意2 小时前
【CVPR2023】奔跑而非行走:追求更高FLOPS以实现更快神经网络
人工智能·深度学习·神经网络·算法·机器学习·卷积神经网络