HashMap延伸---单向链表中环的问题

上一期在将HashMap扩容的时候,说到了HashMap线程是不安全的,会出现环,由此延伸出了单向链表中环的几个问题。

上期内容忘了的,可以再回顾一下,HashMap之扩容(三),本期主要围绕链表中的环进行讲解

1、判断单向链表中是否有环

2、判断链表中环的长度

3、确定环的入口点

4、求整个单向链表的长度


1、判断单向链表中是否有环

目前常用“快慢指针法”判断单向链表中是否有环,具体如下:

将链表抽象为上图所示,定义两个指针P1和P2,都从起始点A往后移动,其中指针P1每次移动两个节点,P2每次移动1个节点。
如果链表中有环的话,P1和P2的速度差会在环内形成追赶问题,最终P1会追赶上P2,在环的某个节点处(上图C点)相遇,即此时的节点完全一样。此算法的时间复杂度为O(n),空间复杂度为O(1)。

2、判断链表中环的长度

如上图,指针P1和P2在C点相遇后,让P1和P2继续往后遍历,到下一次相遇点(其实也是在C点)。此过程中若P2走的长度为L2,P1走过的长度为L1=2*L2.即P2走过的路程是P1的两倍。此时环的长度为:L1-L2.

3、确定环的入口点

确定环的入口点,即确定出B点的位置,这个要基于一定的数学计算,如下图:

根据图中所列数据可以得出,在第一次相遇的时候
P1走的距离为:a+n*L+b, P2走的距离为:a+b.  且L=b+c
因为P1的速度是P2的两倍,所以第一次相遇的时候,有如下公式成立
a+n*L+b=2*(a+b) --->n*L=a+b---->a=n*L-b=n*(b+c)-b=(n-1)(b+c)+c=(n-1)L+c
最终得出如下公式结论: a=(n-1)L+c
转化为文字是:从A到B的距离与从C走到B点的距离相等,其中从C到B可能是在环里走了n圈,最后停在了B点。
进而可以转化为两个指针P3和P4分别从A点和C点出发,每次走一个节点,第一次相遇的地方会在B点,即在环入点相遇。
通过以上可以得出结论:
在第一次相遇后,一个指针从起始点移动,另一个指针从相遇点移动,下一次相遇的节点就是环的入口

4、求整个单向链表的长度

通过2和3中已经能知道AB的长度a和环的长度L,进而就可以知道整个链表的长度S=a+L

猜你喜欢

转载自blog.csdn.net/jerry_player/article/details/79224566