【leetcode刷题笔记】Linked List Cycle II

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?


判断一个链表是否有环。

题解:

设置两个指针p1和p2;

p1每次走一步,p2每次走两步,如果在这个过程中,p2为空,则没有环;否则两个指针必然相遇,则有环;

接下来找环的起点,将p1挪动到链表起始,p2保持在两指针相遇的地方不动,然后p1和p2分别每次走一步,则下一次相遇的地方为环的起点。

先贴代码如下:

 1 class ListNode {
 2     int val;
 3     ListNode next;
 4     ListNode(int x) {
 5         val = x;
 6         next = null;
 7     }
 8 }
 9  
10 public class Solution {
11     public ListNode detectCycle(ListNode head) {
12         ListNode p1 = head;
13         ListNode p2 = head;
14         
15         while(p2 != null){
16             p1 = p1.next;
17             p2 = p2.next;
18             if(p2 != null)
19                 p2 = p2.next;
20             else 
21                 return null;
22             if(p1 == p2)
23                 break;
24         }
25         
26         if(p2 == null)
27             return null;
28         p1 = head;
29         while(p1 != p2){
30             p1 = p1.next;
31             p2 = p2.next;
32         }
33         return p1;
34     }
35 }

证明如下(证明参考:http://stackoverflow.com/questions/2936213/explain-how-finding-cycle-start-node-in-cycle-linked-list-work

如上图所示,假设从链表起点到环的起点距离为m,从环的起点到p1和p2第一次相遇的地方距离为k,环的长度为n。设第一次相遇的时候p1走过了S步,则p2走过了2S步,所以

S = m + pn + k      (1)

2S = m + qn + k    (2)

其中p1绕圆走过了完整的p圈,p2绕圆完整的走过了q圈。

(1)式代入(2)式中得:2(m+pn+k) = m+qn + k  ->  m+k = (q - 2p)n   (3)

对于任意一个链表m和n是固定的,所以我们只要证明存在整数p,q,k使得(3)式成立即可。

去p = 0, k = mn-m, q = m, 则(3)式成立,所以p1,p2一定会相遇在距离环的起点(mn-m)的地方。

接下来证明如果使得p1回到环的起点,p2保持不动,两个指针以相同的速度前行,则下一次相遇的地方一定是环的起点。

从(3)式可以看出,m+k是环的长度的整数倍,所以p2从相遇的地方走m步,一定回到环的起点,而p1从链表起点走m步也走到环的起点,所以p1和p2以相同的速度前进,下一次相遇的地方一定的环的起点。

证毕。

 

 

posted @ 2014-07-04 20:03  SunshineAtNoon  阅读(414)  评论(0编辑  收藏  举报