给你一个单链表的头节点
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)