今天学习的内容之一是循环链表与快慢指针。
初始化:
将slow、fast 指向head结点
更新规则是:慢指针走一步,快指针走两步
slow = slow.next,fast = fast.next.next
由于链表里有环,则有以下几点结论
1、快慢指针必定在某个结点相遇(下文称为相遇结点)
推导:
试想一下,因为链表有环,是不存在结点指向None的情况,所以快慢指针会一直在环里走动。
假设慢指针进入链表的环的时候,快指针与慢指针之间的距离m步。
此时继续按照规则更新,则两者相差m-1步。
直到两者距离相差0步,即相遇了。
2、如果快慢指针同时在相遇结点同时出发,则在下一次相遇的结点时,将快指针走过的步数减去慢指针的步数便可以得出环长度。
3、在头结点和相遇结点同时开始,每次往前走一步,两个结点相遇时,便是环的入口结点。
设:入口结点为p,相遇结点为q,两者相距m步,问题则是:求头结点head到入口结点p的距离a
s = a + m
注意:当慢指针进入环之后,两者相遇的步数必定小于len。也就是说,慢指针还没走完一圈就会被追上。
2s = a + m + k * len(k为快指针绕环的圈数,len为环的长度)
可得:
a = k * len - m
相遇结点位置是:a + m