题目描述:https://oj.leetcode.com/problems/linked-list-cycle-ii/
首先使用Floyd 判圈算法,可以判断链表是否存在环,然后,还要求出环开始的点。
这里求环开始的点需要一些推导:
设从链表起点到环起点的距离为m,环的周长为s,fastPtr和slowPtr在距离环起点k处相遇。
相遇时slowPtr的运行长度:ls = m+s*n1+k;fastPtr的运行长度 lf =m+s*n2+k。同时注意到,fastPtr的速度是slowPtr的2倍,则 2*ls = lf,则ls = (n2-n1)*s。即ls是圈周长的倍数。在slowPtr和fastPtr相遇后,将slowPtr移动到链表头。slowPtr和fastPtr一同移动,当slowPtr移动到距离链表头m的距离,fastPtr移动到距离链表头i+m的距离。因为i为周长的倍数。这样看,fastPtr相当与从链表头部开始,移动到环的开始(m)处,然后绕了环n圈,回到开始。这样fastPtr和slowPtr的相遇处即是环的开始处。
package Linked_List_Cycle_II;
public class Solution {
class ListNode{
int val;
ListNode next;
ListNode(int x){
val = x;
next = null;
}
}
public ListNode detectCycle(ListNode head) {
if(head==null) return null;
ListNode slowPtr = head;
ListNode fastPtr = head;
boolean flag = true;
do{
if(fastPtr.next == null||fastPtr.next.next == null){
flag = false;
break;
}
slowPtr = slowPtr.next;
fastPtr = fastPtr.next;
fastPtr = fastPtr.next;
}while(slowPtr!=fastPtr);
if(flag == false )
return null;
else{
slowPtr = head;
while(slowPtr != fastPtr){
slowPtr = slowPtr.next;
fastPtr = fastPtr.next;
}
return slowPtr;
}
}
}