网上很多关于环形链表的算法,但是相信不是每一个人都可以透彻理解。我在这里为大家推演一下,相信理解了下面的推演过程,我可以保证你对于找环形链表的算法再也不惧怕,牢记于心中,以不变应万变。
废话少说先上代码:
import java.util.*;
class Program {
public static LinkedList findLoop(LinkedList head) {
LinkedList slow = head.next;
LinkedList fast = head.next.next;
while(slow != fast){
slow = slow.next;
fast = fast.next.next;
}
// slow和fast值相同,说明在环形链表中相遇,此时把fast指针移动到head节点。
fast = head;
while(slow != fast){
fast = fast.next;
slow = slow.next;
}
return fast;
}
static class LinkedList {
int value;
LinkedList next = null;
public LinkedList(int value) {
this.value = value;
}
}
}
代码很简单,但是想要知道为什么第二个while循环结束就能得到环形链表开始的地方,且听我娓娓道来,一定要仔细的看图,跟上我的文字思路:
图中的几个变量说明:
D
变量代表的是head节点 -> 环形节点开始的地方。P
变量代表的是slow节点和fast节点相遇时,slow在环形链表中的步长。R
变量代表的是slow节点还有多少步长就到达环形链表开始的地方。T
变量代表的是链表的总长度。
通过图中变量目前可以得到T = D + R + P
的结论,但是目前好像还无法解开这道题,最关键的就是R
变量了,如何让slow节点走完R
变量停下,得到环开始的位置呢?让我们继续推演!!!
已知slow的步长是1,fast节点的步长是2,假设slow = x
,那么fast = 2x
已知slow节点走过的步长是 D + P
,所以slow = X = D + P
,fast = 2X = 2D + 2P
fast节点比slow节点多走了一个P的距离,因此继续得出T = 2D + P
现在有两个对于T
变量的结论,T = D + R + P
和T = 2D + P
把P变量去掉,得出D + R = 2D
,也就是D + R = D + D
,继续去掉一个D变量,得出D = R
。也就是两个指针,一个走完D
的距离,另一个也必定能走完R
的距离,而R
距离走完后停下,必定是环开始的地方。
所以才会把fast指针移动到head处,fast和slow指针都以步长为1的方式走,fast走的是D
的距离,而slow走的是R
的距离,因此当他们全部走完,值相同时,就是环开始的地方。
完结撒花🎉,有小伙伴不懂的地方可以一起讨论哦,大家一起成长一起进步。