如何判断一个单链表有环,并且求出交汇处

单链表有环的情景如下,为了方便起见,假定入口之前的链表长度为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直到两者相遇,相遇的结点便就是所求结点

代码明天奉上,晚安

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值