分为两步
第一步 还是利用快慢指针,假设有环的话在利用快慢指针终会相会于一个节点。
第二步。然后从这节点出发每次出发走一步,同一时候从根节点出发每次出发也走一步则他们两个指针相遇的地方就是环的入口。
第一步好解释那么第二步是为什么呢?
网上有非常多解法大都是从数学的角度来分析。有公式也有推算非常不直观。我从图形的角度来看的话就相对理解起来简单非常多。
将图摊开成一条线,如果我们有环并且如果快指针就多走了一圈就与慢指针相遇了(多走n圈事实上也是一样的,画出图来也不难理解。仅仅是画起来麻烦索性就以一圈来代表)
红线表示快指针走了2m 蓝线表示慢指针走了m,从图中能够很直观的看出来,假设把蓝色的线移到上面的红线上,遮挡住红线。则红线还剩下多少
就是一个y 和一个z, 我们知道多走的长度为m,即y+z=m,对照蓝色的线也是是m,就是x+z=m
所以直接推出来x = y 那么我们的第二步想必大家就都理解了。
假设说快节点走了非常多圈我们能够自己绘图发现事实上最后还是归结到上面这个图的模型上来。
附上代码
/**
* Definition for singly-linked list.
* class ListNode {
* int val;
* ListNode next;
* ListNode(int x) {
* val = x;
* next = null;
* }
* }
*/
public class Solution {
public ListNode detectCycle(ListNode head) {
if(head==null){
return null;
}
ListNode slow = head;
ListNode fast = head;
ListNode now = head;
while(fast.next!=null&&fast.next.next!=null){
fast = fast.next.next;
slow = slow.next;
if(fast==slow){
now = slow;
break;
}
}
if(fast.next==null||fast.next.next==null)
return null;
else{
ListNode start = head;
while(start!=now){
start = start.next;
now = now.next;
}
return start;
}
}
}