Leetcode 234. 回文链表

77 阅读2分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第19天,[点击查看活动详情] (juejin.cn/post/714765… "juejin.cn/post/714765…")

1.题目

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

示例 1:

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

2.思路

判断链表是否为回文链表,回文链表也就是说链表从中间向两边发散,每次都是相同值的节点,那么我们可以考虑将链表转成一个数组,因为回文子串也意味着从两头往中间比较,每一步都相同,但是对于链表来说无论是从中间向两边发散还是从两边往中间比较,操作都比较麻烦,而转换成数组后就可以采用双指针分别从头尾向中间指,直到两个指针相交每次比较都相等就返回true否则就返回false,但是这种解法需要额外的空间,不满足题目的要求。

我们采用另一种的办法,我们之所以要把链表转成数组,是因为链表向上循环不好实现,那我们可以考虑采用另一种方案也就是找到链表的中间节点,然后把后半部分进行反转,然后再进行循环比较。

首先我们采用快慢指针的方式找到链表的中间节点,也就是快指针一次走两步,慢指针一次走一步,快指针走到头时慢指针正好走到中间位置,然后从慢指针的下一个位置开始反转链表,再将慢指针指向表头,进行循环比较。

//反转链表
const reverseList = (head) => {
    let prev = null;
    let curr = head;
    while (curr !== null) {
        let nextTemp = curr.next;
        curr.next = prev;
        prev = curr;
        curr = nextTemp;
    }
    return prev;
}
//快慢指针找到中间
const endOfFirstHalf = (head) => {
    let fast = head;
    let slow = head;
    while (fast.next !== null && fast.next.next !== null) {
        fast = fast.next.next;
        slow = slow.next;
    }
    return slow;
}

var isPalindrome = function(head) {
    const first = endOfFirstHalf(head);
    const half = reverseList(first.next);
    let p1 = head;
    let p2 = half;
    while (p2 != null) {
        if (p1.val != p2.val){
            return false
        }
        p1 = p1.next;
        p2 = p2.next;
    }        

    return true;
};