「链表/双指针」leetcode 234.回文链表(简单)

210 阅读2分钟

这是我参与11月更文挑战的第12天,活动详情查看:2021最后一次更文挑战

一、了解题目

附上原题链接:234. 回文链表

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

示例 1:

img

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

示例 2:

img

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

二、题解分析

1、降低空间复杂度的思考

在做题时,我们通常要尽可能的去降低时间复杂度和空间复杂度。那对于降低空间复杂度来说,主要有以下思考:

  • 我们要尽量地去避免使用 O(n) 的额外空间,通常使用的方法就是改变输入
  • 因此,我们可以将链表的后半部分进行反转(修改链表结构),然后将前半部分和后半部分进行比较
  • 比较完成后我们应该将链表恢复原样;
  • 虽然不需要恢复也能通过测试用例,但是使用该函数的人通常不希望链表结构被更改;
  • 该方法虽然可以将空间复杂度降到 O(1) ,但是在并发环境下,该方法也有缺点;
  • 在并发环境下,函数运行时需要锁定其他线程或进程对链表的访问,因为在函数执行过程中链表会被修改。

2、题解步骤

依据以上题意和对复杂度的分析。整个流程可以分为以下五个步骤:

  • 找到前半部分链表的尾节点;
  • 反转后半部分链表;
  • 判断是否回文;
  • 恢复链表;
  • 返回结果。

三、代码实现

依据上面的题解,我们将用 js 来实现这道题。具体实现代码如下:

/**
 * 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}
 */// 翻转链表
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) {
    // 1.首先先判断链表是否为空,为空时则直接返回true
    if (head == null) return true;
​
    // 2.找到前半部分链表的尾节点并反转后半部分链表
    const firstHalfEnd = endOfFirstHalf(head);
    const secondHalfStart = reverseList(firstHalfEnd.next);
​
    // 3.判断是否是回文
    let p1 = head;
    let p2 = secondHalfStart;
    let result = true;
    while (result && p2 != null) {
        if (p1.val != p2.val) result = false;
        p1 = p1.next;
        p2 = p2.next;
    }        
​
    // 4.还原链表并返回结果
    firstHalfEnd.next = reverseList(secondHalfStart);
    return result;
};

四、复杂度分析

时间复杂度: O(n) ,其中 n 指的是链表的大小。

空间复杂度: O(1) 。我们只会修改原本链表中节点的指向,而在堆栈上的堆栈帧不超过 O(1)


思路来源:回文链表

以上就是关于回文链表的题解,不知道对小伙伴们是否有帮助呢?

我们下期见👋👋👋