以前同窗跟我讨论如何判断一个链表是否有环,以及如何得知环的入口点,说是Programming Pearls (编程珠玑)上面的习题。html
如下是个人理解,以及认为大部分文章中关于“定理:碰撞点p到链接点的距离=头指针到链接点的距离” 并不正确,讨论见文末。算法
图片来源编程
当时我想哈希的方式处理,不过这个方法知识理论可行,实际不具备操做性。spa
后面上网查了资料,问题的解法很巧妙。用速度为1和2的两个指针遍历链表,若是有环的话,这两个指针就会碰撞。bingo, 问题解决。.net
经过相似的思路,能够简单的计算环的长度,即在碰撞点继续前进,当他们再次相遇时,快的指针比慢的指针恰好多走一圈,也就是环的长度。指针
这道题让我想到了小学时候的数学题,一个跑得快的人和一个跑得慢的人,他们多久后相遇。htm
寻找环的入口点方法是从头指针、碰撞点以同样的速度出发(注意不是1和2了),相遇的地方就是环的入口点。很简单很巧妙,可是这个证实这样作为何会对。blog
我看了网上的资料,大部分给了算法,而后看了一篇证实,以为思路不够简单明了。因而我本身想出了以下的方法,用来理解。图片
首先很容易获得以下的等式,看符号解释便可明白,由于快的指针走的距离是慢的指针的2倍。get
$$2(L_{HE} + d) = L_{HE} + kL + d$$
其中$L_{HE}$,为头指针到入口处的距离
$L$ 为环的长度
$d$是入口处到它们相遇的地放的距离
$k$为天然数,快的指针在与慢指针碰撞时走的圈数
经过上式可得 为$L_{HE} = kL -d $, 有了这个等式,咱们能够进行以下简单明了的理解了:
速度同样的两个指针,假设指针Head从头指针出发,指针Entry从碰撞点出发,当它们相遇时,Entry走过的路程为$kL - d$,指针Head的距离$L_{HE} $。这不明显相等吗?一个等式,化简一下就出来了,稍微理解一下就能够了。
还有一个提醒是,当快慢指针相遇时,慢指针没有走完环。这个稍微一想,或者列个式子就能够明白了。
参考文章 (“问题3:有定理:碰撞点p到链接点的距离=头指针到链接点的距离,”不少文章都这么写,可是我的认为这个等式不成立,由于它们会在链接点相遇不等于它们到链接点的距离相等。举个例子,环长度为2,头指针到环的入口处为10,显然等式不成立。真正成立的等式,读者本身能够动手列一下。
原文首发于博客园 Hall Of FAME