leetcode原题:234.回文链表
数据:[1,2,2,1]:
采用链表形式存储:
// 创建链表
var linkList = {
val: 1,
next: {
val: 2,
next: {
val: 2,
next: {
val: 2,
next: {
val: 1,
next: null
}
}
}
}
}
法一:通过函数调用栈的方式,反序判断
/**
* 判断回文链表
* 解决:通过闭包的形式保存头指针,并根据函数调用栈后进先出的机制,保存每次的值,再与头指针相向遍历来判断
* 如果有两边判断时有一方为false则直接为假
* @param head
* @returns {boolean}
*/
var isPalindrome = function(head) {
// 使用let声明变量主要是为了防止外部引用(在非严格模式下)
let left = head;
function traverse(right) {
if (right == null) return true;
let res = traverse(right.next);
// 只有当之前的值相等才再比较其值
res = res && (right.val === left.val);
left = left.next;
return res;
}
return traverse(head);
};
法二:通过慢指针,快指针的方式,反转链表,使其一一匹配的方式
/**
* 采用慢指针和快指针的方式,快指针用于判断奇偶以便构造慢指针
* 慢指针用于指明当前所处后半部分的哪部分,用于反转后半部分,以至将反转之后的后半部分与之前的链表进行一一比较
* @param head
* @returns {boolean}
*/
var isPalindrome = function(head) {
// 反转 slower 链表
let right = reverse(findCenter(head));
let left = head;
// 只比前半部分
while (right != null) {
if (left.val !== right.val) {
return false;
}
left = left.next;
right = right.next;
}
return true;
};
// 如何找到这个慢指针:如果是偶数,则表示慢指针走了快表的一半距离,如果是块表,则比快表一半少一步,则需要再走一步
function findCenter(head) {
let slower = head, faster = head;
while (faster && faster.next != null) {
slower = slower.next;
faster = faster.next.next;
}
// 如果 faster 不等于 null,说明是奇数个,slower 再移动一格
if (faster != null) {
slower = slower.next;
}
return slower;
}
// 反转后半部分
function reverse(head) {
let prev = null, cur = head, nxt = head;
while (cur != null) {
nxt = cur.next;
cur.next = prev;
prev = cur;
cur = nxt;
}
return prev;
}