142.环形链表II
题意: 给定一个链表,返回链表开始入环的第一个节点。 如果链表无环,则返回 null。
为了表示给定链表中的环,使用整数 pos 来表示链表尾连接到链表中的位置(索引从 0 开始)。 如果 pos 是 -1,则在该链表中没有环。
说明:不允许修改给定的链表。
解法
对于这道题,可以设定两个指针,同时从头节点出发,一个一次走一步,一个一次走两步,即一快一慢。如果存在环,那么这两个指针一定会在环中相遇。如下图所示:
慢指针一次走一步,所以慢指针走过的路程为 x + y。
快指针在环内走了 n 圈追上慢指针,所以快指针的路程为 x + y + n(y + z),其中 y + z 为一圈的路程。
由于快指针比慢指针快了一倍,可以得到以下公式:
2(x + y) = x + y + n(y + z)
要求的是 x,所以对以上公式进行处理得到:
x + y = n(y + z)x = n(y + z) - yx = (n - 1)(y + z) + y + z - yx = (n - 1)(y + z) + z
其中 n 是大于等于 1 的,所以当 n 等于 1 时,得到 x = z。
这时只需慢指针从头出来,快指针从相遇点出发,每次都走一步,那么相遇点就是环入口。
代码
var detectCycle = function(head) {
if(head === null || head.next === null) {
return null
}
let slow = head
let fast = head
do {
slow = slow.next
fast = fast.next.next
} while(slow !== null && fast !== null && fast.next !== null && slow !== fast)
if(slow === null || fast === null || fast.next === null) {
return null
}
slow = head
while(slow !== fast) {
slow = slow.next
fast = fast.next
}
return slow
};