1.反转链表
解法
1.双指针
思路:
- 定义两个指针pre和cur,pre从链表头部之前的null开始,而cur则从链表的头部head开始依次向后移动
- 使用变量nextNode将当前结点的next保存下来,然后将当前结点的next指向上一个结点pre
- 循环向后(当前结点是否为null作为判断条件)移动pre和cur两个指针,
pre = cur;cur=nextNode(这也是我为什么要使用变量nextNode保留当前结点的next的原因,如果不使用一个变量存储下来当前结点的next值,那么cur.next在上一步重新赋值时就会丢失) - 最后返回pre即为反转后的链表
var reverseList = function(head) {
let pre = null
let cur = head
while(cur != null) {
let nextNode = cur.next
cur.next = pre
pre = cur
cur = nextNode
}
return pre
};
2.回文链表

解法
1.双指针
思路
- 定义两个指针fast和slow,两指针均从链表的头结点出发,fast每次移动两个单位长度,slow每次移动一个单位长度
- fast移动到终点会出现两种情况:①fast最后刚好在链表的最后一个结点的话此时slow指针正好在链表的中间结点,那么就说明该链表长度为奇数;②fast最后指向了null的话,该链表长度为偶数;
- 如果链表长度为奇数,需要将slow指针从中间结点向后移动一位,使得slow指针的右侧链表长度小于左侧链表长度
- 然后反转右侧链表后将fast指针放在左侧链表的头结点,slow指针放在翻转后的右侧链表的头结点
- while(slow!=null)说明右侧链表没有遍历完,两指针同时向后移动一个单位,如果
fast.val != slow.val则说明链表不是回文链表就返回false - 直到slow == null就还没返回false则说明是回文链表,就返回true
//用于链表翻转的方法
function reveseList(head) {
let pre = null, cur = head
while(cur != null) {
let nextNode = cur.next
cur.next = pre
pre = cur
cur = nextNode
}
return pre
}
var isPalindrome = function(head) {
let fast = head, slow = head
while(fast != null && fast.next != null) {
fast = fast.next.next
slow = slow.next
}
//当first为不为null但是first.next为null,说明该链表长度为奇数
//此时slow处于链表正中间,需要将slow再往下移动一个单位,将中间结点赋给左侧链表
if(fast != null) {
slow = slow.next
}
//将右侧的链表进行反转
slow = reveseList(slow)
fast = head
//此时slow是经反转后的链表
//fast指针指向左侧链表的头结点,slow指针也指向右侧链表的头结点
while(slow != null) {
if(slow.val != fast.val) return false
slow = slow.next
fast = fast.next
}
return true
};