题目描述
请判断一个链表是否为回文链表。
示例 1:
输入: 1->2
输出: false
示例 2:
输入: 1->2->2->1
输出: true
进阶:
你能否用 O(n) 时间复杂度和 O(1) 空间复杂度解决此题?
解法思路
本题可以使用双指针算法来解决,先找到链表中点位置,然后将中点之后的链表进行翻转,最后将翻转后的链表与原链表进行对比即可。
具体做法如下:
- 定义快指针
fast和慢指针slow,让它们分别指向链表的头结点。 - 使用快慢指针找到链表的中点位置,即当快指针到达链表末尾时,慢指针恰好走到了链表中点位置。
- 将链表中点位置之后的部分进行翻转。
- 同时遍历翻转后的链表和原链表,如果两个链表的值不相等,则说明该链表不是回文链表,返回
false;否则继续遍历,直到遍历完成,返回true。
代码实现
function isPalindrome(head: ListNode | null): boolean {
if (head === null) {
return true;
}
let slow = head;
let fast = head;
while (fast && fast.next) {
slow = slow.next;
fast = fast.next.next;
}
// 初始化:reverse -> null;slow -> next
let reverse = null;
while (slow !== null) {
let temp = slow.next;// 取出下个节点,便于继续遍历
// 翻转:slow -> next 变成 reverse <- slow
slow.next = reverse;
// 后移:头节点,slow节点后移
reverse = slow;
slow = temp;
}
while (reverse !== null && head !== null) {
if (reverse.val !== head.val) {
return false;
}
reverse = reverse.next;
head = head.next;
}
return true;
};
复杂度分析
-
时间复杂度为 O(n),其中 n 是链表的长度。找到链表中点位置需要遍历一次,翻转后半部分链表需要遍历一次,对比两个链表需要遍历一次。
-
空间复杂度为 O(1),因为只使用了常数级别的额外空间。