带环链表求环的第一个节点的问题

文章介绍了如何利用fast指针(每次走两步)和slow指针(每次走一步)在链表中找到第一个环的入口。通过图像化和代数分析,证明了fast指针在慢指针进入环后,经过两倍慢指针的圈数后会再次相遇,从而确定环的入口。
摘要由CSDN通过智能技术生成

给定一个链表的头节点 head ,返回链表开始入环的第一个节点。 如果链表无环,则返回 null

关于以上问题的解答,已经有许多可以参考的思路。在许多的解决思路中,都会涉及对代数知识的理解并且要求具有一定的洞察力。有没有一种图像化的描述来解决这个问题呢?
在尝试解决这个问题之前,有几个前提条件需要描述清楚。

第一,对于任何一个回路,如果存在一个fast指针,每次向前走两步。存在一个slow指针,每次向前走1步。那么这两个指针在回路中必定相遇。(之后所说的fast指针都是走两步,slow指针走一步)

第二,fast、slow指针在一个回路中的某个节点相遇,则fast、slow指针之后相遇的节点也是这个节点。

第三,fast、slow指针从起始节点出发(起始节点可能就是环的入口)。fast指针先进入环,当slow指针进入环时,fast指针与slow指针继续在环内前进,直到fast、slow指针相遇。slow指针在环内走过的长度不超过环的长度。

现在正式进入正题

图1

如图1所示,这个链表是带有一个环的,入环节点是第二个节点。如果存在一个fast指针和一个slow指针,同时从第一个节点开始走,这两个指针最终都会进入环并且在环中相遇(由fast指针在环中追上进入环后的slow指针)。很容易得出,fast、slow指针会在节点4相遇。这个问题不妨想到在起始位置(节点1),fast、slow指针是处于“相遇”状态,进入环后,最终也会相遇。他们之间有没有什么关联?实际上,可以这样思考:节点2是环的入口,节点1是节点2的前一个节点,在环中的视角来看,节点4也是节点2的前一个节点。从节点1出发进入环等价于从节点4开始出发,最终fast、slow指针都会在节点4再次相遇。

将这个思想推广,对于入环前有任意个节点、环的长度(节点数)为任意的情况。将相遇节点假想为一开始fast、slow指针所处的起始位置,slow指针经过n圈,fast经过2n圈后,又在此处相遇(显然n>=1)。那么这个结论正不正确呢?如果正确,则我们可以直接得出以相遇节点为起点,绕环路n-1圈再加上从相遇节点到入环节点的距离等于从起始位置到入环节点的距离。

简要的证明过程

图2
如图2所示,从起始节点到入环节点之间可能有任意个节点,环内的节点也可能有任意个。fast、slow指针同时从起始位置出发,fast指针先进入环,当slow指针到达入环节点时,快指针有可能已经在环内绕了很多圈并位于环的某个节点处。接下来,fast、slow指针都处于环内,fast指针将追击slow指针,直到某个位置fast、slow指针相遇。如图2所示的相遇节点。

由前提条件3,slow指针进入环后所走过的长度不超过一个环路的长度。如图2所示,slow指针进入环,从入环节点到相遇节点的弧段就是slow指针走过的长度。所以slow指针实际走过的长度是从起始位置到相遇节点的长度。fast指针走了这个长度的2倍。
图3
fast指针所走过的距离的描述:
如图3所示,slow指针刚到入环节点时,从fast指针的位置到入环节点的距离等于从入环节点到相遇节点的距离。这是因为fast指针的行进速度是slow指针的2倍,从相遇节点逆推,slow指针逆向走了x,则fast指针逆向走了2x的距离。fast此时所在的这个节点的意义在于fast刚好走了L的2倍距离,因为slow指针刚到入环节点,slow走了L

此时,我们神奇地发现fast走过的距离减去在环外走过的距离L,刚好等于L,无论fast在环内走了多少圈。然后,slow指针从入环节点向前走x,fast指针从当前位置向前走2x刚好追上slow指针,位置恰好是相遇节点。
注意:这里fast走完一圈,是以入环节点为起点最终走到入环节点。按照这样的逻辑,当slow指针刚到入环节点时,fast就在如图3所示的位置。
图4
如图4所示,fast可能在环内走很多圈,当slow到达入环节点时,fast指针停在了如图4所示的位置处。经过刚才的证明,已经知道当slow到入环节点时,fast在环内走过距离等于L,即等于slow从起始位置到入环节点的距离。
图5
现在假设fast以相遇节点为起点,最终走到相遇节点为一圈,则当slow刚好走到入环节点时,fast就刚好走到入环节点,这个距离也等于L。所以可以将slow指针从起始位置到相遇节点所走过的距离假想为从相遇节点开始,经过n-1圈到达入环节点的距离,再加上从入环节点到相遇节点的距离。这样刚好经过n圈后返回相遇节点。而fast则走过了2倍与此的距离,即2n圈。这样就证明了假想:将相遇节点假想为一开始fast、slow指针所处的起始位置,slow指针经过n圈,fast经过2n圈后,又在此处相遇(显然n>=1)。

编程思想
假设起点在相遇节点处,则当slow走到入环节点时,fast也会刚好到达入环节点。并且已经说明了,slow走的距离和fast在环内走的距离相等。这样,就可以定义两个指针,一个指向起始位置,另一个指向相遇节点,当他们第一次相遇时,即地址相同时,这个地址所对应的节点就是环的第一个节点。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值