【转】求单链表是否存在环路

一种O(n)的办法就是(搞两个指针,一个每次递增一步,一个每次递增两步,如果有环的 
话两者必然重合,反之亦然): 
关于这个解法最形象的比喻就是在操场当中跑步,速度快的会把速度慢的扣圈 

可以证明,p2追赶上p1的时候,p1一定还没有走完一遍环路,p2也不会跨越p1多圈才追上 

我们可以从p2和p1的位置差距来证明,p2一定会赶上p1但是不会跳过p1的 

因为p2每次走2步,而p1走一步,所以他们之间的差距是一步一步的缩小,4,3,2,1,0 
到0的时候就重合了 

根据这个方式,可以证明,p2每次走三步以上,并不总能加快检测的速度,反而有可能判别 
不出有环 

既然能够判断出是否是有环路,那改如何找到这个环路的入口呢? 

解法如下: 当p2按照每次2步,p1每次一步的方式走,发现p2和p1重合,确定了单向链表有                                        
环路了 

接下来,让p2回到链表的头部,重新走,每次步长不是走2了,而是走1,那么当p1和p2再次 
相遇的时候,就是环路的入口了。 

这点可以证明的: 

在p2和p1第一次相遇的时候,假定p1走了n步骤,环路的入口是在p步的时候经过的,那么有 

p1走的路径: p+c = n;        c为p1和p2相交点,距离环路入口的距离 

p2走的路径: p+c+k*L = 2*N;  L为环路的周长,k是整数 

显然,如果从p+c点开始,p1再走n步骤的话,还可以回到p+c这个点 

同时p2从头开始走的话,经过n不,也会达到p+c这点 

显然在这个步骤当中p1和p2只有前p步骤走的路径不同,所以当p1和p2再次重合的时候,必 
然是在链表的环路入口点上。 

转自http://blog.163.com/libo_5/blog/static/15696852011431111052369/

posted @ 2013-11-22 10:07  DKMP  阅读(271)  评论(0编辑  收藏  举报