检测链表是否存在环的算法证明

今天看到c专家编程的最后,有一处关于检测链表是否存在环的算法介绍,这个问题和算法之前在很多地方有看见,大致是有三个问题:1.给你一个单向链表判断是否有环;2.求出环的长度;3.给出环的开始节点。算法是这样:让两个指针指向表头,一个每次移动一步,叫做慢指针,一个每次移动两步,叫做快指针,一直循环移动,如果最后两者都碰到NULL指针则表示没有环,如果最后两者指向同一个节点表示有环。至于问题2,3则是可以扩展得到,从快慢指针相遇的那个节点开始,令一个新的指针开始遍历,他从起点回到起点所经历过的步数就是所求长度length,而环的开始节点可以这样求,让一个指针p1指向链表头,另一个p2指向离他length步的节点,p1,p2同时往前步步移动,他们相遇的节点既是环的起点。

 

问题2,3依赖问题1,且显而易见,但是问题1的解法怎么用准确的数学方法来证明,在存在环的情况下快指针一定会和慢指针相遇吗?这里有一个比较好的证明:http://stackoverflow.com/questions/3952805/proof-of-detecting-the-start-of-cycle-in-linked-list

 

证明过程大致如下:

《检测链表是否存在环的算法证明》

链表如上图所述,pSlow,pFast分别对应快慢指针,在指针在链表上移动的时候有

pSlow = x

pFast = 2(x+1)

当pSlow到达m时pFast = 2(m+2), 这时候pSlow与pFast都在环上移动,当pSlow移动了t步后

pSlow = m + t  ==>  m + t %n

pFast  = 2*(m + t )  ==> m + (m + 2t)%n

现在,当且仅当m +t%n = m +(m+2t)%n 时 pSlow = pFast,快慢指针相遇,解这个等式:

m +t%n = m +(m+2t)%n  ==>  t%n = (m+2t)%n ==> (m+t)%n = 0

m是非负整数,n是正整数,t是正整数,显然对于任意的m,n必然存在一个t使得等式成立。

    原文作者:persistentsnail
    原文地址: https://www.cnblogs.com/persistentsnail/p/3294917.html
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞