原题链接:
力扣https://leetcode.cn/problems/linked-list-cycle-ii/
这类链表题目一般都是使用双指针法解决的,例如寻找距离尾部第 K 个节点、寻找环入口。
算法流程:
设两指针 fast,slow 指向链表头部 head,fast 一次走2步,slow 一次走1 步。
第一种结果: fast 指针走过链表末端,说明链表无环,直接返回 null。因为若有环,fast与slow距离越来越短,两指针一定会相遇。
第二种结果: 当fast == slow时, 两指针在环中第一次相遇 。
分析此时fast 与 slow走过的步数关系 :
设链表共有 a+b个节点,其中 链表头部到环形入口 有 a个节点(不计链表入口节点), 链表环有 b个节点。设两指针分别走了 f,s步,则有:
fast 走的步数是slow步数的 2倍,即 f=2s;
fast 比 slow多走了 n个环的长度,即 f=s+nb( 双指针都走过 a步,然后在环内绕圈直到重合,重合时 fast 比 slow 多走环的长度整数倍 );
以上两式相减得:f=2nb,s=nb,即fast和slow 指针分别走了 2n,n个 环的周长
如果让指针从链表头部一直向前走并统计步数k,那么所有 走到环入口节点时的步数 是:k=a+nb(先走a步到入口节点,之后每绕 1圈环( b 步)都会再次到入口节点)。
而目前,slow 指针走过的步数为 nb步。因此,我们只要想办法让 slow 再走a步停下来,就可以到环的入口。那么a怎么求?
构建一个指针,此指针和slow 一起向前走 a 步后,两者在入口节点重合。而从链表头开始走到入口正好是距离a。
具体代码与注释如图: