前言
想要解决这一道算法题,建议先把 LeetCode:206.反转链表 以及 LeetCode 141.环形链表 这两题做一做!对解决回文链表这一题很有帮助。
回文链表的题目如下:
请判断一个链表是否为回文链表。
示例 1: 输入: 1->2 输出: false
示例 2: 输入: 1->2->2->1 输出: true
进阶:
你能否用 O(n) 时间复杂度和 O(1) 空间复杂度解决此题?
解题思路
- 掌握反转链表的方法
- 掌握快慢指针的思维模式
解题步骤
- 找到链表的中间节点,从而把链表分成前半段和后半段。
- 反转后半段链表
- 把前半段链表的值和后半段链表的值进行比较,保持一致说明是回文链表。否则,就不是。
代码演示
/**
* Definition for singly-linked list.
* function ListNode(val) {
* this.val = val;
* this.next = null;
* }
*/
/**
* @param {ListNode} head
* @return {boolean}
*/
// 反转链表
const reverseList = function (head) {
let p1 = head;
let p2 = null;
while (p1) {
const tmp = p1.next;
p1.next = p2;
p2 = p1;
p1 = tmp;
}
return p2;
}
// 前半部分链表的尾结点(利用快慢指针的思想,找到链表的中间结点)
const findPreHalfEnd = function (head) {
let p1 = head;
let p2 = head;
while (p1 && p1.next && p2 && p2.next && p2.next.next) {
p1 = p1.next;
p2 = p2.next.next;
}
return p1;
}
var isPalindrome = function(head) {
if (head === null) return true; // 空链表也是回文链表
const preHalfEnd = findPreHalfEnd(head);
const lastHalfStart = reverseList(preHalfEnd.next);
let p1 = head;
let p2 = lastHalfStart;
let result = true;
while (result && p2) { // 循环
if (p1.val === p2.val) {
p1 = p1.next;
p2 = p2.next;
} else {
result = false
}
}
// 复原后半段链表
preHalfEnd.next = reverseList(lastHalfStart);
return result;
};
时间复杂度:O(n)
空间复杂度:O(1)