单向链表有证明其是否有环形,求其进入环形入口节点
简单的办法,将所有点的内存地址值放到hashset中,然后遍历单向链表。
只要链表中的节点在hashSet中已经存在,就说明存在该单向链表存在环形。且第一个出现相同的点为环形入口。
还有一种额外空间为O(1)的方法,采用快慢指针。
证明快慢指针相遇后,将慢指针从原点重新开始就能在环形入口相遇
在证明上述之前,我们先证明一套高中数学的追赶问题。
求两人在环形跑道上,第一次相遇的位置
题:有一个长度为L的环形跑道,在跑道上有两个人a1、a2,他们的速度分别为v、2v。其中,a1在起点,a2在距离起点x米的地方,求他们相遇的点。其中x<L。
证明:a1、a2两人相遇,相当于在t时间后,两人跑过的距离和跑道周长L取余相等。
即:(vt)%L = (x+2vt)%L
由于a2跑过的距离比a1要长,所以可以调整为
x+2vt = vt+nL 即:相遇的时候,a2跑过的距离加上起始的x米距离,比a1跑过的距离多n(n为整数)个跑道
那么第一次相遇的时候,相当于n=1
即:x+2vt=vt+L
那么,他们相遇点距离起点距离为 vt=L-x米
快慢指针,在环形区域相遇后,距离入口距离
题:有一个环形单向链表,其非环形区域节点为L1,环形区域节点为L2。有两个指针,他们同时从head节点开始,沿着链表进行遍历。其中,快指针pf的速度Vf=2节点/次,慢指针的速度为ps速度Vs=1节点/次。求两个指针相遇后,距离入口处多远。
根据上面操场的问题,我们假设经过t=L1/Vs次之后,作为我们题目的开始时间。
即:初始状态为如下图,慢指针Ps在环形入口出,快指针Pf在环形区域中距离入口L1的地方。那么,在这种状态下求Pf、Ps在环形区域,他们相遇的节点在哪里呢?
这里根据非环形长度L1、环形长度L2不同情况进行讨论。
当L1 < L2
当L1小于L2的时候,那么Ps走到环形入口的时候,Pf在环形区域内走过了L1的节点数,但是还没达到一圈。那么,他们第一次相遇的时候可以表示为:
(L1+tVp)%L2 = tVs % L2 其中v=1,t为指针走的次数。相当于Pf和Ps在环形中走过的距离,和环形节点L2取模后相对。
那么,由于Vp=2Vs,且当他们相遇的时候,Pf走过的距离比Ps走过的距离多n倍
即:L1+t2v = tv + nL2
第一次相遇的时候,n=1,v=1
即:L1+2t=t + L2
所以:t=L2-l1 即,当Ps进行环形后,两个指针相遇的位置为t=L2-L1。
此时,如果把快指针放回链表head出按照Vp=1格/次前进,再经过L1的距离,次数t=L1/v后,Pf开始进到环形入口,Ps此时也正好回到环形入口。
当L1 > L2
当L1>L2的时候,我们把Ps进到环形入口节点的时候,Pf距离环形入口的位置设为i,其i=L1 % L2
即Pf距离环形入口的位置为, i=L1 - mL2 其中m为整数
i+2t=t+L2
t= L2 - i = L2 - (L1 - mL2)
t=(m+1)L2 - L1
同上,把快指针放回链表head出按照Vp=1格/次前进,再经过L1的距离,Ps距离环形入口 t2= t + L1 = (m+1)L2 - L1 + L1 = (m+1)L2 即在环形入口。
当 L1 = L2
当两者相等的时候,当Ps进到环形入口节点的时候,Pf已经在进入环形区域且经过了L1的距离,此时正好在环形入口处。
以上证明完成,若有差错,请个人看官斧正。