求链表内环的入口节点-Java

时间:2022-10-04 16:43:51

步骤:
1.设置快慢两个指针,slow和fast,每次slow走一步slow.next,而fast走两步fast.next.next.
2.如果链表有环肯定可以在环内的一个节点相遇.
3.此时,slow指向相遇的节点,而fast指向头结点,然后slow和fast继续走,每次都走一步,slow.next,fast.next.当slow和fast指向同一个节点的时候就是入口节点,那么这是为什么呢?

为什么slow.next和fast.next指向的同一节点就是入口节点呢?
一开始,判断链表有没有环时,当fast若与slow相遇时,slow肯定没有走遍历完链表(此处我还没有证明,但举例好像都是),而fast已经在环内循环了n圈(1<=n)。假设slow走了s步,则fast走了2s步(fast步数还等于s 加上在环上多转的n圈)。设环长为r,则:
求链表内环的入口节点-Java

//fast是slow速度的两倍,那么他们走的距离就必然满足下面的式子,fast比slow多走的就是绕环的圈数
2s=s+nr;
s=nr;

设整个链表长L,入口节点与相遇节点距离为x,起点到环入口节点的距离为a。

a+x=s
所以a+x=nr
a+x=(n-1)r+r=(n-1)r+L-a
所以a=(n-1)r +(L-a-x)

(L – a – x)为相遇节点到环入口点的距离,由此可知,从链表头到环入口点等于(n-1)倍的循环内环+相遇点到环入口点,于是我们从链表头、与相遇点分别设一个指针,每次各走一步,两个指针必定相遇,且相遇第一点为环入口点。