链表题目的解决, 通常要结合画图来理解
876 链表的中间结点
入门级别, 快慢指针即可解决
var middleNode = function(head) {
let quick = head,
slow = head
while (quick!==null && quick.next!==null) {
quick = quick.next.next
slow = slow.next
}
return slow
};
160 相交链表
让我用一道很浪漫的题开启大家的链表之旅吧!
关键词: 重走一遍你的路, 我们终究会相遇
function getIntersectionNode (headA, headB) {
let pA = headA
let pB = headB
while (pA!==pB) {
pA = (pA===null) ? headB : pA.next
pB = (pB===null) ? headA : pB.next
}
return pA
}
206 反转链表
pre, cur, next三指针
本题目不使用dummy节点, 使用pre和cur双节点的方式, 由于单链表的限制, 额外使用一个next指针记录cur节点的下一个节点的位置, 每次遍历时, 让cur指向pre, 并让pre前移, cur前移(指向next)
/**
* Definition for singly-linked list.
* function ListNode(val, next) {
* this.val = (val===undefined ? 0 : val)
* this.next = (next===undefined ? null : next)
* }
*/
/**
* @param {ListNode} head
* @return {ListNode}
*/
var reverseList = function(head) {
// pre始终落后cur和next一个身位, cur和next指向同一个节点
let pre = null,
cur = head,
next = head
while (cur!==null) {
// 使用next指针记录cur后一位的地址
next = cur.next
cur.next = pre
// pre前移一位
pre = cur
// cur前移一位
cur = next
}
return pre
};
利用es6的解构赋值, 我们有更为精巧的解法
var reverseList = function(head) {
// pre始终落后cur一个身位, cur指向当前节点
let pre = null,
cur = head
while (cur!==null) {
// 利用es6的解构赋值, 你甚至不需要额外的next指针
[cur.next, pre, cur] = [pre, cur, cur.next]
// pre, cur移动的顺序也可以改变
// [cur.next, cur, pre] = [pre, cur.next, cur]
}
return pre
};
92 反转链表 II
pre, cur, next三指针 + 额外存储
想法:
- 反转位置m到位置n之间的链表
- 将原链表与反转后的链表拼接
步骤:
- 初始化变量: pre指向前方, curr遍历当前链表, 二者依次增加, pre始终落后curr一个身位
- 将pre, curr递增到位置m之前, 使用pre2和curr2分别存储当前pre和curr的位置
- 反转位置m到位置n之间的链表
- 利用pre2和curr2, 将反转后的部分链表与原链表拼接
var reverseBetween = function (head, m, n) {
let prev = null;
let curr = head;
for (let i = 1; i < m; i++) {
prev = curr;
curr = curr.next;
}
let prev2 = prev;
let curr2 = curr;
for (let i = m; i <= n; i++) {
[curr.next, prev, curr] = [prev, curr, curr.next];
}
if (m > 1) {
prev2.next = prev;
} else {
head = prev;
}
curr2.next = curr;
return head;
};
141 环形链表
快慢指针
- 创建两个指针都指向头部, 快指针走两步, 慢指针走一步
- 如果二者能相遇, 则为环形链表
/**
* Definition for singly-linked list.
* function ListNode(val) {
* this.val = val;
* this.next = null;
* }
*/
/**
* @param {ListNode} head
* @return {boolean}
*/
var hasCycle = function(head) {
if (head===null) return false
let fast = head,
slow = head
while (fast.next!==null && fast.next.next!==null) {
fast = fast.next.next
slow = slow.next
if (fast === slow) {
return true
}
}
return false
};
142 环形链表 II
原理图解:
代码:
var detectCycle = function(head) {
if (head===null) return null
let fast = head,
slow = head,
isCircle = false
while (fast.next!==null && fast.next.next!==null) {
fast = fast.next.next
slow = slow.next
if (fast===slow) {
// 此时说明有环, 退出循环
fast = head
isCircle = true
break
}
}
if (!isCircle) return null
while (fast!==slow) {
fast = fast.next
slow = slow.next
}
return fast
};
328 奇偶链表
奇偶双指针
/**
* Definition for singly-linked list.
* function ListNode(val, next) {
* this.val = (val===undefined ? 0 : val)
* this.next = (next===undefined ? null : next)
* }
*/
/**
* @param {ListNode} head
* @return {ListNode}
*/
var oddEvenList = function(head) {
if (head===null) return null
if (head.next===null) return head
let odd = head
let even = head.next,
evenHead = even
while (even!==null && even.next!==null) {
odd.next = odd.next.next
odd = odd.next
even.next = even.next.next
even = even.next
}
odd.next = evenHead
return head
};