前置算法:单链表确定是否存在环
采用双指针法判断是否带环,设置一个快指针,一个慢指针,快指针每次走两个节点,慢指针每次走一个节点。
如果快指针走到链表尾部了(下一节点为null),证明没有环
如果快指针和慢指针相遇了,说明存在环
知道存在环了,怎么判断环起点?
当快慢节点相遇时,快节点所走路程是慢节点的两倍。
此时,设链表头到环起点的距离是p,slow在环内走的路程为s,fast在环内走的路程为f
同时,因为fast和slow此时相遇,设相遇点距环起点距离为x,环的长度为c,如图:
可得:
s%c = c-x
f%c=c-x
慢节点的总路程为:s+p
快节点的总路程为:2(s+p)
快节点在环内的路程就是:2s+p
可得:
(2s+p)%c = c-x
s%c = c-x
设2s+p为nc + c-x,s为mc+c-x
所以:
(2s+p)-(s)= nc-mc
设n-m=o
s=oc-p
此时慢节点在环内的路程为oc-p,当慢节点再走p,环内路程就为oc,回到了环起点
如果重新设置一个游标节点,从链表起点开始,与慢节点一起走,两个节点同时走p,慢节点回到了环起点,游标节点也走到了环起点
由此我们可以在判断是否存在环的算法上进行扩展,当快慢节点相遇后,快节点回到链表开始节点,并与慢节点一起每次走一步,当两个节点相遇时,就得到了环起点