单链表有环的情景如下,为了方便起见,假定入口之前的链表长度为L,循环长度为K
循环链表示意图
我们可以用两个指针,p1每次移动一格,p2每次移动两格,初始化都为头结点HEAD
随着指针慢慢推进,一定会出现以下的情况
某一时刻两指针的情况
第一步
现在,我们可以假定再经过t次移动之后,两者会在某一处相遇,对照上图
对于P1,t次移动后的位置为t % K
对于P2, t次移动后的位置为(x + 2 * t) % K
P1和P2相遇的充要条件为 t % K = (x + 2 * t) % K
显然,t = K - x就可以满足条件,至此,P1总共遍历了 L + K - x 个结点,也就是说P1不需要遍历所有的结点便可以和P2相遇,即有循环
当然,如果在遍历过程中只要P2或者P2->next为NULL,就break,说明此链表没有环
第二步
现在要求循环的起始点,显然上图中是阴影部分的0处,
由上面一步可知,当P1移动到所示位置时用了L次,P2移动的格数为 2*L ,并且满足
2*L = L + x + r * K 即 L = x + r *k (r>=0为P2在循环里面转的圈数) #1
在上一步中,最后P2的位置为 K - x, 要让P2移动到阴影部分0的位置,只需要P2再移动L格,
因为根据上面的等式#1 , P2移动L 格之后的位置为
(K - x + L) % K = (K - x + x + r * K )= ((r + 1) * K) % K = 0
刚好在交汇处
那么,怎么才能让P2移动L次呢,显然,如果我们将P1再次指向HEAD,每次移动一格,并且此时P2每次也移动一格
移动L次之后,p1也在0处,两者便相遇了,相遇的地方就是所求的交汇处,那么我们要做的就是
不断地移动P1和P2直到两者相遇,相遇的结点便就是所求结点
代码明天奉上,晚安