如何判断一个链表是否有环?以及对一些文章的错误的看法
之前同学跟我讨论如何判断一个链表是否有环,以及如何得知环的入口点,说是Programming Pearls (编程珠玑)上面的习题。
以下是我的理解,以及认为大部分文章中关于“定理:碰撞点p到连接点的距离=头指针到连接点的距离” 并不正确,讨论见文末。
当时我想哈希的方式处理,不过这个方法知识理论可行,实际不具有操作性。
后面上网查了资料,问题的解法很巧妙。用速度为1和2的两个指针遍历链表,如果有环的话,这两个指针就会碰撞。bingo, 问题解决。
通过类似的思路,可以简单的计算环的长度,即在碰撞点继续前进,当他们再次相遇时,快的指针比慢的指针刚好多走一圈,也就是环的长度。
这道题让我想到了小学时候的数学题,一个跑得快的人和一个跑得慢的人,他们多久后相遇。
寻找环的入口点方法是从头指针、碰撞点以一样的速度出发(注意不是1和2了),相遇的地方就是环的入口点。很简单很巧妙,但是这个证明这样做为什么会对。
我看了网上的资料,大部分给了算法,然后看了一篇证明,觉得思路不够简单明了。于是我自己想出了如下的方法,用来理解。
首先很容易得到如下的等式,看符号解释即可明白,因为快的指针走的距离是慢的指针的2倍。
$$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
转载于:https://www.cnblogs.com/celthi/p/4896127.html
- 链表问题:如何判断一个链表有环,以及环的长度,起始位置。
- 笔试面试3 将一个数分解成质因数的形式以及如何判断一个数是否是质数
- java cloneable以及如何判断一个字符串是否为数字。
- 如何判断一个链表是否有环,如果有环,并找出环的入口
- 如何判断一个类是否支持某属性和方法以及如何判断IOS的版本
- 在做一些复杂的类型转换之前(比如将一个数据转换成一个属性的类型,属性可能为可空类型)先判断该类型是否为可空类型,否则会报如下错误:
- php學習 --- 调节器 以及如何判断一个字符串是否是邮件
- php學習 --- 调节器 以及如何判断一个字符串是否是邮件
- 首先如何判断一个链表是否有环,并找出环的入口
- 如何判断一个类是否支持某属性和方法以及如何判断IOS的版本
- 单链表中如何判断是否有环以及判断环的入口点
- [数据结构] 如何判断一个链表是否有环? 环的入口? 环的长度?
- 如何判断一个链表是否有环?
- 如何判断两个链表是否相交,以及交点
- 判断一个链表是否有环以及环的位置入口
- 如何判断一个单向链表是否有环路?
- 【摘】给定一些单元格的坐标,如何判断它们是否能合并为一个单元格?
- 浮点数在intel上的二进制存储结构,以及如何判断一个浮点数是否为整数
- 浮点数在intel上的二进制存储结构,以及如何判断一个浮点数是否为整数
- 判断一个类是否支持某属性和方法以及如何判断IOS的版本