24.回文链表

52 阅读1分钟

题目链接

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

解法1 暴力解法

思路

最简单的办法就是先遍历整个链表,将链表内容缓存下来。

然后采用双指针的方式遍历是否是回文链表。

代码

function isPalindrome(head: ListNode | null): boolean {
    let cur = head;
    const valList = [];
    while (cur) {
        valList.push(cur.val);
        cur = cur.next;
    }

    for (let i = 0, j = valList.length -1; i <= j; i++, j--) {
        if (valList[i] !== valList[j]) {
            return false;
        }
    }
    return true;
};

时空复杂度

时间复杂度:两次遍历 O(n)

空间复杂度:使用数组额外存储 O(n)

解法2 反转链表再比较

思路

题目中没有禁止修改链表,所以我们可以将链表反转,然后再顺序比较是否回文。

那既然要反转,肯定不是将整个链表翻转,而是找到链表的中点,将后半段链表翻转。

然后再使用双指针顺序遍历两个链表的节点是否相等。

代码

function isPalindrome(head: ListNode | null): boolean {
    if (!head || !head.next) {
        return true;
    }

    let slow = head;
    let fast = head;
 
    // 找到链表中点
    while (fast !== null && fast.next !== null) {
        fast = fast.next.next;
        slow = slow.next;
    }
    
    // 翻转后半段链表
    let pre = null;
    while (slow !== null) { // 翻转链表常用模板
        let next = slow.next;
        slow.next = pre;
        pre = slow;
        slow = next;
    }
    
    // 比较是否回文
    let left = head;
    let right = pre;
    while (right !== null) {
        if (left.val !== right.val) {
            return false;
        }
        left = left.next;
        right = right.next;
    }
    return true;
};

时空复杂度

时间复杂度:O(n)

空间复杂度:使用了常数变量 O(1)