前言
在上节环形链表1的基础上,我们来解环形链表2的题
模拟链表跑道图(憋住笑)
我们把模拟逻辑描述下:
- 甲、乙分别1倍速(1步1节点)、2倍速(1步2节点)从起点head处出发,第一次在O点相遇;
- 甲走的距离为A+B,只要跑道有环,那么乙肯定比甲多跑n圈才能相遇,那么乙走的距离为A+n(B+C)+B;
- 乙走的距离肯定是甲的2倍,那么2(A+B) = A+n(B+C)+B
- 到这里上面的公式我们转化一下,我们最终要求的是P点也就是入环点,那么简化公式为:A=n(B+C)-B;
- 这里n至少是大于等于1的,乙至少比甲多跑一圈吧才能说明有环,上面公式里n(B+C) =》(n-1)(B+C)+B+C,那么得到的公式为A = (n-1)(B+C) + C
那么我们从最后的公式可以总结得出: 让甲从起点head处、乙从环内相遇点O以相同的速度走,那么他们肯定会在入环点相遇,无论乙在环内走了多少圈,甲乙第一次相遇一定是在入环点P,乙走的距离符合(n-1)(B+C) + C = A
开始解题
先用环形链表1的方法判断链表有无环: var detectCycle = function(head) {
if(!head) return null;
let pre = head,cur = head;
while(cur && cur.next){
pre = pre.next;
cur = cur.next.next;
// 如果有环,代入我们上述的结论
if(pre === cur) {
// 1、让甲即pre从head点开跑
pre = head;
// 2、只要甲、乙没到入环点P,那么pre和cur指向的节点就不相等
while(pre !== cur) {
// 3、让甲从head点,乙在环内相遇点O以相同的速度起跑,即pre和cur都是1步1节点
pre = pre.next;
cur = cur.next;
}
// 出了循环,说明pre === cur,即此时甲乙在入环点P相遇,那么pre所在当前节点就是入环点,返回即可
return pre;
}
}
// 无环情况按照题目直接返回null
return null;
};