思路
寻找环的入口,需要做如下的数学证明。先给出示意图如下:
做如下假设:
- 设直线段的端点为
X点 - 环的入口点为
Y点 - 快慢指针相遇的点为
Z点 - 其中,有
XY−→−=l,YZ−→−=r0ZY−→−=c,
当快慢指针相遇时,有下面的式子:
由于快指针走过的路程是慢指针的两倍,所以有:
整理得:
即
所以,相遇点到入口的距离加上(k-1)个环等于端点到入口的距离。
所以,分别设两个指针从端点和相遇点开始移动,当他们相遇时,即为环的入口。
public class LeetCode142 {
public ListNode detectCycle(ListNode head) {
// 利用快慢指针找相遇点
ListNode slow = head;
ListNode fast = head;
while(fast != null && fast.next != null){
slow = slow.next;
fast = fast.next.next;
if(slow == fast) break;
}
if(fast == null || fast.next == null) return null;
//slow指针从头指针出发,fast指针从相遇点出发
slow = head;
while(slow != fast){
slow = slow.next;
fast = fast.next;
}
return slow;
}
}