Floyd判圈算法

leetcode习题287 Find the Duplicate Number 在答案中看到了floyd’s tortoise and hare 算法,知道了如果有限状态机、迭代函数或者链表存在环,那么是需要算法检测环是否存在。检测算法有三种:Floyd龟兔算法、Brent算法、Gosper算法。

Floyd龟兔算法

算法描述

Floyd龟兔算法是一种指针算法。该算法仅使用移动速度不同的两个指针就能检测出是否有环。Floyd龟兔算法解决以下问题:1检测是否有环。2环的起点节点。3环的长度。
1 检测是否有环。
想象在一个环形跑道上跑步,两个人同时出发,出发以后速度快的人终究会在某一点和速度慢的人相遇。一般这个时候相遇,速度快的人比速度慢的人至少多跑一圈。
在这里插入图片描述
我们假设列表的开始节点是S,环上的起始节点是P,第一次相遇的节点是M。S和P的距离是p,从P和M的距离是m,从M到p的距离是n。指针t和h初始状态下都指向S。接着t每次只有1步,h每次走2步。只要二者没有相遇,就一直按着这个速度走下去。当h无法前进(到达队列末尾)的时候,可以判断没有环。如果t和h在某点再次相遇,则确定有环。
举一个迭代函数的例子。有函数f定义域和值域都是 S = {0,1,2,3,4,5,6,7,8},从 x 0 = 2 x_0=2 x0=2开始,不断重复调用f,能够产生一个序列:2,0,6,3,1,6,3,1,6,3,1…产生了一个环:6,3,1。
这里写图片描述
定义:S是一个有限集合,f是一个函数,从S到S的一个映射, x 0 x_0 x0可以是S中的任意一个元素。对于任意的 i > 0 i>0 i>0 x i = f ( x i − 1 ) x_i=f(x_{i-1}) xi=f(xi1) μ \mu μ是换上的起点节点的最小下标, λ \lambda λ是环的长度。一定有 x μ = x λ + μ x_\mu=x_{\lambda+\mu} xμ=xλ+μ
证明:如果有环存在,则对于任意的整数 i > = μ i>=\mu i>=μ并且 k > 0 k>0 k>0,都有 x i = x i + k λ x_i=x_{i+k\lambda} xi=xi+kλ。对于特定的k来讲,一定存在使得 i = k λ i=k\lambda i=kλ,那这时候 x i = x 2 i x_i=x_{2i} xi=x2i。至此,说明了速度不同的两个指针可以在某点相遇。

2 计算环长度
当t和h相遇在M点。因为相遇的点一定在环上。这时候保存h不动,t按之前的速度继续前进,直到和h再次相遇,这个过程中移动的步数就是环的长度。

3 环的起始节点确定
在确定是否有环的过程中,h走的距离是t走的距离的2倍。c为环长。t走的距离是 s 1 = p + m + a ∗ c s1=p+m+a*c s1=p+m+ac,h走的距离是 2 ∗ s 1 = p + m + b ∗ c 2*s1=p+m+b*c 2s1=p+m+bc,两式子相减得到: s 1 = ( b − a ) ∗ c = p + m + a ∗ c s1=(b-a)*c=p+m+a*c s1=(ba)c=p+m+ac,得到p+m=环的整数倍。
为了找到环的起点,t回到起点,h在当前位置。同时向前,他们再次相遇一定在P点。为什么呢?因为从S到P的距离是p,从P到M的距离是m,因为m+p是环长的整数倍,所以当h走过距离p的时候也一定达到了P点。

算法时间复杂度:令S到P的距离为m,环的长度为n,时间复杂度 O ( m + n ) O(m+n) O(m+n)
空间复杂度:O(1)。

参考
网页1
网页2
网页3

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值