纸上得来终觉浅,绝知此事要躬行
算法推导
当hare
的移动速度是tortoise
的 2 倍,
设起始点到环的入口的距离是T
,环的长度是C
,
当tortoise
第一次走到环的入口entry point
时,我们假设这是tortoise
与hare
之间的在环上的距离是r
,
从start point
开始出发到tortoise
第一次走到环的入口时,hare
移动的距离是 T + r + k*C,k >= 0
,
又因为,hare
移动的速度是tortoise
的两倍,且这时tortoise
移动的距离是T
,所以hare
移动的距离是 2T。
得到等式 A T + r + k*C = 2T,k >= 0
简化得到等式 B r + k*C = T,k >= 0
当 tortoise 第一次走到环的入口entry point
时,而这时tortoise
与hare
之间的距离是 r,
那么如果tortoise
现在就不继续移动的话,hare
还需要往前走C-r
才能追上tortoise
。
但是hare
在往前追赶tortoise
的时候,tortoise
也在移动,而hare
的移动速度是tortoise
的两倍,
所以hare
可以追上tortoise
,并且需要往前走2*(C-r)
才能追上tortoise
。
当hare
移动了2*(C-r)
的距离追上tortoise
的时候,tortoise
从相对于环的入口entry point
移动了C-r
。
所以,在tortoise
与hare
第一次在环上相遇时,环的入口entry point
到这个点meet point
的距离是C-r
, 而从这个相遇点meet point
再往前移动r
,就又回到了环的入口entry point
。
在hare
与tortoise
第一次相遇的这个时候,将hare
从meet point
重新放到起始点start point
,tortoise
仍放在这个相遇点meet point
,
然后让它们以相同的速度开始移动,
根据等式 B r + k*C = T,k >= 0
,
tortoise
和hare
必然会在环的入口点entry point
再次相遇
入口entry point
找到后,就能很容易得到T
,
然后入口entry point
,让tortoise
停下,hare
继续跑一圈,就能得到 C
。
算法应用
- 链表有环检测 两个指针,慢指针移动速度为 1,快指针移动速度为 2,判断两个指针是否相遇
- 找出有环链表的入口节点 当两个指针相遇时,将其中一个指针重新放到链表头,然后让两个指针移动速度都为 1,当两个指针再次相遇,就找到了有环链表的入口节点
- 计算环长度 在入口节点放置两个个指针,一个指针不动,一个指针移动速度为 1,两个指针相遇,就可计算出环的长度
算法实现
golang
- 链表有环检测
leetcode 141
1 | /* |
- 找出有环链表的入口节点
leetcode 142
1 | /* |
写在结尾
算法实现仔细想想就是初中做过的数学题目啊,哎,过了这么多年竟然忘的一干二净。