这道题做起来简单,但是证明比较麻烦。自己的证明很可能有错误,还望指正。
一 是否有环
(1)用追击法,一个指针每次前进1步,另一个指针每次前进2步。
设链表中不包括环的长度为L1,环的长度为L2.
假设走s步之后相交,等价于 式(1)(s-L1)mod L2 = (2s-L1)mod L2有解。即s步之后相交<=>)(s-L1)mod L2 = (2s-L1)mod L2有解
由式(1)得到,n* L2+p=s-L1 (2)
m*L2+p=2s-L1 (3)
由(2)(3)得到 (m-n)L2=s (4)
由于s是可变的,上式显然有解。
算法为:一个指针每次前进1步,另一个指针每次前进2步。每次都对比,如果相同则表明相遇,如果到链尾则退出说明没相遇。
(2)而且,我们可以证明在一圈内即可追上。即算法复杂度为O(n)。
当L2>=L1,令s=(L1+k)=L2,保证式子(4)有解
当L1>L2,s=(L1+k)=n1 * L2,我们可以知道K可以小于L2(取K=L2-L1modL2)
二 求第一个交点
根据式子(4)=> (m-n-1)L2+L2=s => (m-n-1)L2+ P1+P2=L1+P1 <=> (m-n-1)L2+P2=L1
(P1为定义第一个相交点到追击相遇点的长度,P2为相遇点到第一个相交点的长度,即P1+P2=L2)
这个式子表明链表中不包括环的长度 等于 相遇点到第一个相交点的长度加上环的长度的整数倍。
则算法为:一个指针从相遇点出发,一个指针从链表头开始,而第一次相遇的点即为第一个相交点。