234. 回文链表
一、将值复制到数组中后用双指针法
1、为什么要将值复制到数组中?
因为在链表中访问一个特定的节点需要O(n),而这个题目是需要遍历一半链表数量的节点,前后进行比较。
2、时间复杂度
3、代码实现
var isPalindrome = function(head) {
// 利用数组存储链表的值
let vals = [];
while(head){
vals.push(head.val);
head = head.next;
}
// 利用双指针进行前后元素的比较
for(let i=0,j=vals.length-1; i<j; i++,j--){
if(vals[i] != vals[j]){
return false
}
}
return true;
};
二、快慢指针
避免使用 O(n)O(n) 额外空间的方法就是改变输入。我们可以将链表的后半部分反转(修改链表结构),然后将前半部分和后半部分进行比较(反转后的前后链表应该是一样的)。
1、找到中间节点,将链表拆分 2、反转后半部分链表 3、判断回文,前后链表是否相等 4、恢复链表 5、返回结果
// 中间节点,注意这里当有两个中间节点时,返回第一个节点。所以循环条件改变
var findMid = function(head){
let slow=head, fast=head;
while (fast.next !== null && fast.next.next !== null){
slow = slow.next;
fast = fast.next.next;
}
return slow;
}
// 反转链表
var reverse = function(head){
let pre = null, cur = head;
while(cur){
let temp = cur.next;
cur.next = pre;
pre = cur;
cur = temp;
}
return pre;
}
// 判断回文
var isPalindrome = function(head) {
// 1、找到中间节点,将链表拆分
let mid = findMid(head);
// 2、反转后半部分链表
let second = reverse(mid.next);
// 3、判断回文
while(second){
if(head.val != second.val){
return false
}
head = head.next;
second = second.next;
}
// 4、还原链表并返回结果
mid.next = reverse(second);
return true;
};