内容参考:https://www.jianshu.com/p/88c7e7a8de61

简短概述一下,就是一个大小为n+1的数组中,每个元素的大小范围为[1,n],该数组有且仅有一个重复数字,找出这个重复数。

限制条件为:

  • 时间小于O(n2)
  • 额外空间为O(1)

下面先介绍龟兔赛跑算法。龟兔赛跑算法又称Floyd判圈算法,顾名思义是用来判断链式结构中的环,其具体的作用包括:

  1. 判断链表中是否有环
  2. 如果链表中有环,求出环的长度
  3. 找到环的起点

算法描述

1.判断是否有环

初始状态下,假设起点为S,以及两个在起点位置的龟兔指针分别用slow和fast来表示,让slow与fast同时向前进,同时fast的速度为slow的两倍。若fast不再前进,说明遇到了一个没有后继的节点即不存在环;否则,如果slow与fast相遇,则存在环。

fast,slow = start
while(fast.next!=null&&fast.next.next!=null){slow = slow.next;fast = fast.next.next;if(fast==slow) have_circle();
}

2.求环的长度

接上一步,如果判断链表中存在环,即slow与fast相遇,说明此时slow与fast皆在环内。此时只需让其中一个指针保持不动,然后让另外一个指针继续向前进,当再次相遇则说明走了一圈,即为环长。

count = 1;
fast = slow.next;
while(fast!=slow){fast = fast.next;count++;
}

3.求环的起点

还是接第一步,让slow保持与fast相遇的位置不动,然后让fast从S再次出发,此时让fast的速度与slow保持一致,同时前进,当再次相遇的时候,则为环的起点。看到这里大家肯定一脸懵逼了,下面给出证明:

假定S距离环起点距离为m,环的周长为n,(第一次)相遇点距离环的起点的距离是k。那么当两者相遇时,慢指针(slow)移动的总距离i = m + a * n + k,快指针(fast)的移动距离为2i,2i = m + b * n + k。其中,a和b分别为slow和fast在第一次相遇时转过的圈数。让两者相减(快减慢),那么有i = (b - a) * n。即i是圈长度的倍数。

将一个指针移到出发起点S,另一个指针仍呆在相遇节点M处两者同时移动,每次移动一步。当第一个指针前进了m,即到达环起点时,另一个指针距离链表起点为i + m。考虑到i为圈长度的倍数,可以理解为指针从链表起点出发,走到环起点,然后绕环转了几圈,所以第二个指针也必然在环的起点。即两者相遇点就是环的起点

fast = S;
while(fast!=slow){fast = fast.next;slow = slow.next;
}
  • 再回到之前讲的这道题,虽然给定的是数组,但是可以发现,题中所给数组可以看成链表(不一定是一条链),其中下标为节点地址,元素值为下一节点地址next。由于每个节点都有下一节点,即next都不为空,故链表一定有环。
  • 由于元素范围为[1, n],故下标为0的节点nums[0]不会作为其他节点的下一节点next,因此从0节点开始的链表中一定会存在两个节点的next相同,这个next即为要找的出现两次以上的元素,也就是链表中环的起点。直接套用龟兔算法即可。

        public int findDuplicate(int[] nums) {int slow=0,fast=0;while(true) {slow = nums[slow];fast = nums[fast];fast = nums[fast];if(fast==slow)break;}fast = 0;while(slow!=fast) {slow = nums[slow];fast = nums[fast];}return slow;}
    

弗洛伊德的乌龟和兔子(循环检测相关推荐

  1. 快慢指针(LeetCode寻找重复数),弗洛伊德的乌龟和兔子

    写此篇博客在于总结,记忆之用,欢迎评论补充. 弗洛伊德的乌龟和兔子,即快慢指针. 对于LeetCode287题,寻找重复数,题目如下: 给定一个包含 n + 1 个整数的数组 nums,其数字都在 1 ...

  2. floyd算法 每一层循环_链接列表循环检测– Floyd的循环查找算法

    floyd算法 每一层循环 In this tutorial, we'll be discussing a very popular algorithm which is used to detect ...

  3. 「兔了个兔」龟兔赛跑——乌龟和兔子能否相遇?

    前言 森林里一年一度的赛跑大赛又开始了,乌龟和兔子又被分到了一组,这次乌龟还能跑过兔子吗? 比赛规则: 乌龟每次移动1个单元格,兔子每次移动2个单元格. 随机出现一条赛道,赛道可能为直线,也可能为含有 ...

  4. Gosper 的序列 循环检测

    // 高效程序的奥秘hacker's delight Henry S. Warren, Jr. 著冯速译 // 第5 章位计数5.4 后缀0 计数 // 假设序列X0, X1, X2, ... 是由X ...

  5. java socket 循环读取_java socket tcp(服务器循环检测)

    刚才看了下以前写了的代码,tcp通信,发现太简单了,直接又摘抄了一个,运行 博客:http://blog.csdn.net/zhy_cheng/article/details/7819659 优点是服 ...

  6. //多线程龟兔赛跑问题,乌龟和兔子比赛跑200米的距离,//名叫兔子的线程每执行一次兔子就向前跑5米,每跑50米休息10毫秒,//名叫乌龟的线程每执行一次乌龟就向前跑1米,乌龟会一直跑不休息/

    //多线程龟兔赛跑问题,乌龟和兔子比赛跑200米的距离, //名叫兔子的线程每执行一次兔子就向前跑5米,每跑50米休息10毫秒, //名叫乌龟的线程每执行一次乌龟就向前跑1米,乌龟会一直跑不休息 // ...

  7. skynet源码阅读7--死循环检测

    在使用skynet开发时,你也许会碰到类似这样的警告:A message from [ :0100000f ] to [ :0100000a ] maybe in an endless loop (v ...

  8. 动脉自旋标记磁共振成像在灌注和侧支循环检测的研究进展

    随着2015年国际医学磁共振学会(ISMRM)的灌注研究小组发表的共识声明,以及EU-COST的"ASL in dementia"研究中关于动脉自旋标记磁共振成像(ASL)在临床中 ...

  9. 兔子生兔子循环python_python 实现兔子生兔子示例

    如下所示: # -*- coding: utf-8 -*- # 简述:话说有一对可爱的兔子,出生后的第三个月开始,每一月都会生一对小兔子. # 当小兔子长到第三个月后,也会每个月再生一对小小兔子. # ...

最新文章

  1. matlab bp神经网络
  2. MetaQ Log4j及服务器配置管理
  3. FTP 500 OOPS
  4. 探究php底层运行机制
  5. 安卓开发环境之 Android Studio
  6. 更多Requests的小技巧以及总结
  7. 磁盘管理来安装linux,Linux_在CentOS系统中安装quota来管理磁盘配额,在网络管理的工作中,由于硬 - phpStudy...
  8. 27. 考研与工作怎么选择
  9. Source Insight 的使用
  10. sql08 访问接口没有oraoledb_如何配置交换机和防火墙以访问 Internet?
  11. 修改hosts文件并保存
  12. ardupiolt AP_AHRS库类的分析(一)AP_AHRS_NavEKF
  13. 爬虫chromedriver被识别怎么办?
  14. Solidity智能合约库:区块链工程师的随身工具箱
  15. 计算机硬件 OR CX 1,计算机硬件复习提纲
  16. 计算机解决问题时有什么特点,问题解决
  17. python geometry参数_python arcgis Geometry | 学步园
  18. 网络技术缩写术语大全,还有中英文对比哦。
  19. 《zBrow的资本论》
  20. jQuery Mockjax使用总结

热门文章

  1. 微信记录恢复助手官方版
  2. 青春散场,初心不忘【致毕业季理想主义的你】
  3. c语言程序从哪里开始执行
  4. 阿里云服务器安装并配置nginx代理转发请求
  5. 实现用户登录与用户注册的思路
  6. 全部就业!最高薪资12.5K,黑马这两个学科好牛!
  7. Binder机制之Service Manager(大内总管)
  8. 老男孩MySqI DBA周末班(三期)
  9. atlsd.lib 和 atls.lib冲突
  10. oracle联接,Oracle的联接详解(左连接、右连接、全连接.)