題目:
Given a linked list, return the node where the cycle begins. If there is no cycle, return null
.
Follow up:
Can you solve it without using extra space?
題解:
這個連同I都是很經典的題啦,刷CC150時候就折磨了半天。
其實就推幾個遞推公式就好。。首先看圖(圖引用自CC150):
從連結串列起始處到環入口長度為:a,從環入口到Faster和Slower相遇點長度為:x,整個環長為:c。
明確了以上資訊,就可以開始做運算了。。
假設從開始到相遇,Slower走過的路程長為s,由於Faster的步速是Slower的2倍,那麼Faster在這段時間走的路程長為2s。
而對於Faster來說,他走的路程還等於之前繞整個環跑的n圈的路程nc,加上最後這一次遇見Slower的路程s。
所以我們有:
2s = nc + s
對於Slower來說,他走的路程長度s還等於他從連結串列起始處到相遇點的距離,所以有:
s = a + x
通過以上兩個式子代入化簡有:
a + x = nc
a = nc - x
a = (n-1)c + c-x
a = kc + (c-x)
那麼可以看出,c-x,就是從相遇點繼續走回到環入口的距離。上面整個式子可以看出,如果此時有個pointer1從起始點出發並且同時還有個pointer2從相遇點出發繼續往前走(都只邁一步),那麼繞過k圈以後, pointer2會和pointer1在環入口相遇。這樣,換入口就找到了。
Reference: http://blog.csdn.net/xiaxia__/article/details/19356861
程式碼如下:
2 if(head==null||head.next==null)
3 return null;
4
5 ListNode fast = head,slow=head;
6 while (true) {
7 if (fast == null || fast.next == null) {
8 return null;
9 }
10 slow = slow.next;
11 fast = fast.next.next;
12
13 if(fast==slow)
14 break;
15 }
16
17 slow = head;//slow back to start point
18 while(slow != fast){
19 slow = slow.next;
20 fast = fast.next;
21 }
22 return slow; //when slow == fast, it is where cycle begins
23 }