【面试专题05】Python全栈日记-判断链表是否存在环

版权声明:作者:人学物理死的早 出处:https://blog.csdn.net/weixin_39561473 本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接。 https://blog.csdn.net/weixin_39561473/article/details/86517457

Python的面试题,之前的班考试的时候发的,3道数据结构的题,冒泡之前在学数据结构的时候说过,二叉树之后会讲的,今天说说检查一个单链表是否有环和如何确定环的位置。

首先如何确定有环?

我们给链表设置一个指针,当这个指针一直往下走,如果指针最后等于none,则单链表无环

如果指针一直走,不会停下,那么就说明有环。

确定有环很简单,那如何确定入口呢?也就是环在哪里开始。

我们给单链表的头设置两个指针,一个为slow一个为fast。

slow每次前进1格,slow=slow.next

fast每次前进2格,fast=fast.next.next

这是一个数学问题,如果有环那么fast指针一定会追赶上slow指针

我们假设从head到入口i的长度为a

假设他们在p点相遇

相遇是距离入口为x

环的周长为r

接下来就是通过数学公式的推导来验证a于slow和fast移动时的关系。

警告:接下来的内容纯为数学推导,如果用正常逻辑进行思考是想不明白为啥会这样的,而且我感觉只在fast每次移动距离是slow两倍下成立,我们只需要通过数学推导找出如何求a就行了。

首先:

当slow和fast在p点相遇,因为fast速度是slow的两倍,所以相遇时fast走过的路程也是slow的两倍,所以我们设slow走过的路程为S,fast走过的路程为2S

Fast和slow相遇时,fast肯定在环中不断转圈,假设转了n圈,

因为他们经过的a与x相同,所以他们的路程差就为fast多转的这几圈

所以:2S – S = nr

又因为:2S – S = S

所以:S = nr 、2S = 2nr

又因为fast走过的路程也可以写为:

2S = a + x + nr 

2S = 2nr

所以:

a + x + nr = 2nr

推出:

a = nr -x  = (n-1+1)r – x = (n-1)r +( r – x)

所以最后推导出

a = (n-1)r +( r – x)

这个式子中:

r – x 在图中就是紫色的这段长度

(n-1)r:就是在环中转圈

所以就是说,当我们fast和slow相遇在p后,如果把slow扔在head处,

让slow每次还是前进一格( slow = slow.next )

然后fast从相遇点p开始每次前进一格( fast = fast.next )

那么他们一定会在循环入口i点相遇

因为a = (n-1)r +( r – x)

a 代表slow移动的距离,

a =(n-1)r +( r – x)代表fast从相遇点p出发不论在环中绕多少圈,最后都会在i点与slow相遇。

所以通过slow再次与fast相遇时走过的距离就能直到循环入口i在何处。

过程就是这样,你要去想其中的逻辑就会钻牛角尖,因为这个纯为数学推导,并没有为啥。

接下来通过代码实现:

先创建链表:

然后判断是否有环:

结果:

我修改一下我的链表,让他没环,然后试试能否判断出来:

结果:

猜你喜欢

转载自blog.csdn.net/weixin_39561473/article/details/86517457