題目描述
解題思路
圖中紫色節點爲相遇節點,若快慢指針相遇,必定滿足如下關係:
-
我們使用兩個指針,它們起始都位於鏈表的頭部。隨後慢指針每次向後移動一個位置,而快指針向後移動兩個位置。如果鏈表中存在環,則快 指針最終將再次與 慢指針在環中相遇。
-
當慢指針進入環以後,慢指針還沒走完一個環的時候,快指針必定與之相遇,此時快指針可能已經走了n次環了。因此走過的距離爲:s=a+n*(b+c)+b
-
任意時刻,快指針走過的距離都是慢指針的兩倍 所以 2*(a+b)=a+n*(b+c)+b 所以得出 a=nb+nc-b 即是 a=(n-1)b+nc 即是 a=c+(n-1)(b+c)
-
從3可知,慢指針走完a表示着快指針走完c加n-1圈周長,因此他們會在入口節點相遇。
解題代碼如下
/**
* @description:
* @author: lilang
* @version:
* @modified By:[email protected]
*/
public class ListSolution {
public ListNode detectCycle(ListNode head) {
if (head == null) {
return null;
}
ListNode goFast, goSlow;
goFast = goSlow = head;
boolean isCycle = false;
while (goFast != null && goSlow != null) {
goFast = goFast.next;
if (goFast == null) {
break;
} else {
goFast = goFast.next;
}
goSlow = goSlow.next;
if (goFast == goSlow) {
isCycle = true;
break;
}
}
if (!isCycle) {
return null;
}
goSlow = head;
while (goFast != goSlow) {
goFast = goFast.next;
goSlow = goSlow.next;
}
return goSlow;
}
public static void main(String[] args) {
System.out.println(null == null);
}
}
解題方法二
直接記錄節點是否訪問過,如果訪問過表示存在環,否則不存在。
public class Solution {
public ListNode detectCycle(ListNode head) {
ListNode pos = head;
Set<ListNode> visited = new HashSet<ListNode>();
while (pos != null) {
if (visited.contains(pos)) {
return pos;
} else {
visited.add(pos);
}
pos = pos.next;
}
return null;
}
}