FLOYD判圈
转载一篇博客:http://blog.csdn.net/javasus/article/details/50015687
Floyd判圈算法(Floyd Cycle Detection Algorithm),又称龟兔赛跑算法(Tortoise and Hare Algorithm)。该算法由美国科学家罗伯特·弗洛伊德发明,是一个可以在有限状态机、迭代函数或者链表上判断是否存在环,求出该环的起点与长度的算法。
如果有限状态机、迭代函数或者链表上存在环,那么在某个环上以不同速度前进的2个指针必定会在某个时刻相遇。同时显然地,如果从同一个起点(即使这个起点不在某个环上)同时开始以不同速度前进的2个指针最终相遇,那么可以判定存在一个环,且可以求出2者相遇处所在的环的起点与长度。
算法描述
如果有限状态机、迭代函数或者链表存在环,那么一定存在一个起点可以到达某个环的某处(这个起点也可以在某个环上)。
初始状态下,假设已知某个起点节点为节点S。现设两个指针t和h,将它们均指向S。
接着,同时让t和h往前推进,但是二者的速度不同:t每前进1步,h前进2步。只要二者都可以前进而且没有相遇,就如此保持二者的推进。当h无法前进,即到达某个没有后继的节点时,就可以确定从S出发不会遇到环。反之当t与h再次相遇时,就可以确定从S出发一定会进入某个环,设其为环C。
如果确定了存在某个环,就可以求此环的起点与长度。
计算环长度
上述算法刚判断出存在环C时,显然t和h位于同一节点,设其为节点M。显然,仅需令h不动,而t不断推进,最终又会返回节点M,统计这一次t推进的步数,显然这就是环C的长度。
计算环起点
为了求出环C的起点,只要令h仍位于节点M,而令t返回起点节点S。随后,同时让t和h往前推进,且保持二者的速度相同:t每前进1步,h前进1步。持续该过程直至t与h再一次相遇,设此次相遇时位于同一节点P,则节点P即为从节点S出发所到达的环C的第一个节点,即环C的一个起点。
链表起点为节点S,环起点为节点P,t和h相遇时位于同一节点M,S和P之间的距离为p,P和M之间的距离为m,环长为C,这里两点之间的距离是指从一点走多少步可以到点另外一点。
当t和h相遇时,
t走的步数,step = p + m + a * C,a表示相遇时t走的圈数
h走的步数,2 * step = p + m + b * C,b表示相遇时h走的圈数
两者相减:step = (b - a) * C = p + m + a * C,由此可知t走的步数是环C的倍数,即 p + m 刚好是环长度C的倍数。
t和h在M处相遇,为了计算环C的起点,令h仍位于节点M,而令t返回起点S,随后,同时让t和h往前推进,且保持两者的速度相同:t每前进1步,h前进1步。持续该过程直至t与h再一次相遇,则它们此次相遇时一定位于环的起始节点P。为什么它们此次相遇时一定在环起始节点呢?
t走了p步到达P,h在环C上p步在哪呢?h从M处出发走了p步,相对于环起始位置,h走过的距离是 m + p,而m + p刚好是环长度C的倍数,即h此时也位于环起始节点处,即t和h在P处相遇。据此就可以计算出环起始节点的位置。
算法复杂度
时间复杂度
注意到当指针t到达环C的一个起点节点P时(此时指针h显然在环C上),之后指针t最多仅可能走1圈。若设节点S到P距离为,环C的长度为
,则时间复杂度为
,是线性时间的算法。
空间复杂度
仅需要创立指针t、指针h,保存环长n、环的一个起点P。空间复杂度为,是常数空间的算法。
应用
对于有限状态机与链表,可以判断从某个起点开始是否会返回到访问过运行过程中的某个状态和节点。
对于迭代函数,可以判断其是否存在周期,以及求出其最小正周期。
- 1 int *head = list.GetHead();
- 2 if (head != null) {
- 3 int *fastPtr = head;
- 4 int *slowPtr = head;
- 5
- 6 bool isCircular = true;
- 7
- 8 do
- 9 {
- 10 if (fastPtr->Next == null || fastPtr->Next->Next == null) //List end found
- 11 {
- 12 isCircular = false;
- 13 break;
- 14 }
- 15
- 16 fastPtr = fastPtr->Next->Next;
- 17 slowPtr = slowPtr->Next;
- 18 } while (fastPtr != slowPtr);
- 19 //确定环的起点
- 20 slowPtr = head;
- 21 while(slowPtr != fastPtr)
- 22 {
- 23 slowPtr = slowPtr->Next;
- 24 fastPtr = fastPtr->Next;
- 25 }
- 26 cout<<"the starting point of the cycle is "<<slowPtr<<endl;
- 27 }
FLOYD判圈的更多相关文章
- UVa11549计算器谜题[floyd判圈]
题意: 有个老式计算器,每次只能记住一个数字的前n位.现在输入一个整数k,然后反复平方,一直做下去,能得到的最大数是多少.例如,n=1,k=6,那么一次显示:6,3,9,1... 白书上的题 set, ...
- SGU 455 Sequence analysis(Cycle detection,floyd判圈算法)
题目链接:http://acm.sgu.ru/problem.php?contest=0&problem=455 Due to the slow 'mod' and 'div' operati ...
- UVa 1594 (Floyd判圈) Ducci Sequence
大白书上P42那个计算器的题目就用到了这个办法,Floyd判圈法. 当然,用STL里的map也是可以的. #include <cstdio> #include <cmath> ...
- UVA 11549 CALCULATOR CONUNDRUM(Floyd判圈算法)
CALCULATOR CONUNDRUM Alice got a hold of an old calculator that can display n digits. She was bore ...
- uva11549 Floyd判圈法
题意: 给两个数n, k,每次将k平方取k的前n位,问所有出现过的数的最大值 原来这就是floyd判圈法.. #include<cstdio> #include<cstdlib> ...
- UVA 11549 Calculator Conundrum (Floyd判圈算法)
题意:有个老式计算器,每次只能记住一个数字的前n位.现在输入一个整数k,然后反复平方,一直做下去,能得到的最大数是多少.例如,n=1,k=6,那么一次显示:6,3,9,1... 思路:这个题一定会出现 ...
- leetcode202(Floyd判圈算法(龟兔赛跑算法))
Write an algorithm to determine if a number is "happy". 写出一个算法确定一个数是不是快乐数. A happy number ...
- Floyd判圈算法
Floyd判圈算法 leetcode 上 编号为202 的happy number 问题,有点意思.happy number 的定义为: A happy number is a number defi ...
- UVA - 247 Calling Circles Floyd判圈
思路:利用的Floyd判圈,如果i能到j,j也能到i说明i和j在同一个圈里.每个人的名字可用map编号.最后DFS打印答案即可. AC代码 #include <cstdio> #inclu ...
- Codeforces Gym 101252D&&floyd判圈算法学习笔记
一句话题意:x0=1,xi+1=(Axi+xi%B)%C,如果x序列中存在最早的两个相同的元素,输出第二次出现的位置,若在2e7内无解则输出-1. 题解:都不到100天就AFO了才来学这floyd判圈 ...
随机推荐
- Redis在存取序列化和反序列化性能问题
1. 问题场景 我们在使用Redis的时候经常会将对象序列化存储到Redis中,在取出的时候进行反序列化,如果对象过大在进行序列化和反序列化的时候会有一定性能问题.今天查看了CSRedis源码发现在S ...
- Ubuntu20.04编译ffmpeg
1.安装编译所需工具,GCC 2.安装yasm nasm yasm和nasm是两个编译器,编译ffmpeg需要用到 安装命令: sudo aptitude install yasm nasm 3.安装 ...
- 如何根据不同业务场景调节 HPA 扩缩容灵敏度
背景 在 K8s 1.18 之前,HPA 扩容是无法调整灵敏度的: 对于缩容,由 kube-controller-manager 的 --horizontal-pod-autoscaler-downs ...
- 用C#实现模拟双色球中奖程序 控制台应用程序
前言 这是我在大一第一学期C#的课程设计,要求编写一个模拟双色球彩票的控制台应用程序,用以实现简单的模拟选购彩票. 一.双色球购号号码生成: 1.系统购号:通过"随机数"产生双色球 ...
- Angular入门到精通系列教程(4)- 开发环境搭建以及入手项目
1. 本地开发环境搭建 1.1. node.js 1.2. Angular CLI 2. 开发工具 - Visual Studio Code 第一个Anuglar项目 创建第一个anuglar项目 A ...
- 计算机考研真题 ZOJ问题
题目描述 对给定的字符串(只包含'z','o','j'三种字符),判断他是否能AC. 是否AC的规则如下: 1. zoj能AC: 2. 若字符串形式为xzojx,则也能AC,其中x可以是N个'o' 或 ...
- 【排序基础】1、选择排序法 - Selection Sort
文章目录 选择排序法 - Selection Sort 为什么要学习O(n^2)的排序算法? 选择排序算法思想 操作:选择排序代码实现 选择排序法 - Selection Sort 简单记录-bobo ...
- 关于QTableWidget中单元格拖拽实现
无重写函数实现单元格拖拽 缺点:需要额外设置一个记录拖拽起始行的私有成员变量和拖拽列的初始QList数据成员. 优点:无需重构函数,对于QT中信号和槽的灵活运用 信号和槽 // signal void ...
- CTFshow-萌新赛杂项_签到
查看网页信息 http://game.ctf.show/r2/ 把网页源码下载后发现有大片空白 使用winhex打开 把这些16进制数值复制到文件中 把20替换为0,09替换为1后 得到一串二进制数值 ...
- (四)React Ant Design Pro + .Net5 WebApi:PostgreSQL数据库环境搭建
一.简介 PostgreSQL,开源数据库(没听过小伙伴自己反思一下自行百度) PgAdmin,官方提供的数据库管理工具. 二.环境 1. 官网下载包,安装数据库 tar xjvf /app/pack ...