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。指针t和h初始状态下都指向S。接着t每次只有1步,h每次走2步。只要二者没有相遇,就一直按着这个速度走下去。当h无法前进(到达队列末尾)的时候,可以判断没有环。如果t和h在某点再次相遇,则确定有环。
举一个迭代函数的例子。有函数f定义域和值域都是 S = {0,1,2,3,4,5,6,7,8},从开始,不断重复调用f,能够产生一个序列:2,0,6,3,1,6,3,1,6,3,1….产生了一个环:6,3,1。
定义:S是一个有限集合,f是一个函数,从S到S的一个映射,可以是S中的任意一个元素。对于任意的,。是换上的起点节点的最小下标,是环的长度。一定有
证明:如果有环存在,则对于任意的整数并且,都有。对于特定的k来讲,一定存在使得,那这时候。至此,说明了速度不同的两个指针可以在某点相遇。
2 计算环长度
当t和h相遇在M点。这时候保存h不动,t按之前的速度继续前进,直到和h再次相遇,这个过程中移动的步数就是环的长度。
3 环的起始节点确定
在确定是否有环的过程中,h走的距离是t走的距离的2倍。t走的距离是 ,h走的距离是,得到,也就是说t走的距离是环长度的整数倍,进一步得到,,p+m是环长度的整数倍。
t和h相遇在M点,为了找到环的起点,令h不动,t返回S点,随后同时推进t和h,速度相同,每次前进一步,直到t和h再次相遇。假设他们再次相遇的点是P。证明是否可行。
证明:t从S到P的距离是p,M点相对于P的距离是m,h从M点走过p的距离后:p+m是环长度的整数倍,所以h也一定到达了环的起点P。
第二种的证明:相遇点M的下标,当t从S到P移动距离p到达点的下标是p;同时放在M的指针h移动到点的下标是:,从定义可以知,可以证明两指针在P点相遇。
算法时间复杂度:令S到P的距离为m,环的长度为n,时间复杂度。
空间复杂度:O(1)。