当前位置: 首页 > article >正文

弗洛伊德龟兔赛跑算法(弗洛伊德判圈算法)

弗洛伊德( 罗伯特・弗洛伊德)判圈算法(Floyd Cycle Detection Algorithm),又称龟兔赛跑算法(Tortoise and Hare Algorithm),是一个可以在有限状态机、迭代函数或者链表上判断是否存在环,以及判断环的起点与长度的算法。

昨晚刷到一个视频,来自油管的Joma Tech,视频本身挺有意思的,当然这哥们也很有意思,经常在油管发视频然后在FB就被辞职了,现就职于谷歌。

里面介绍了如何实现下面这个的算法,主要是视频内容很有意思,当然这里还是介绍里面出现的几个算法。

题目:找出数组中的重复数字,数组里只有一个重复的数字,可以重复多次。其中算法的要求是 时间复杂度小于O(n²),空间复杂度是O(1)

题目是很简单,求解的办法也很多,有直接循环查找,为了提高效率还可以使用二分查找,视频中的前两个方法如下:

排序之后,相邻元素如果是相等即为重复数字。但运行的时间复杂度高,比较耗时。不能通过!

def findDuplicate1(nums):
  nums.sort()
  for i in range(1,len(nums)):
    if nums[i]==nums[i-1]:
      return nums[i]

arr1=[1,3,4,2,2]
arr2=[8,1,3,4,2,4,5,4]

print(findDuplicate1(arr1))#2
print(findDuplicate1(arr2))#4

使用字典或set来保存遍历数组里的值,然后判断是否已添加,如果有添加就说明是重复数值了。

这个虽然相较于上面的方法,时间缩短了,但是空间复杂度上来了,比较耗内存。不能通过!

def findDuplicate2(nums):
  seen={}
  for num in nums:
    if num in seen:
      return num
    seen[num]=True

print(findDuplicate2(arr1))#2
print(findDuplicate2(arr2))#4

#或者set()也可以
def findDuplicate2_(nums):
  seen=set()
  for num in nums:
    if num in seen:
      return num
    seen.add(num)
print(findDuplicate2_(arr1))#2
print(findDuplicate2_(arr2))#4

接下来看下符合要求的算法,也就是下面介绍的龟兔算法。

当然这个题目还有一个限定条件,给定一个包含n + 1个整数的数组nums,其中每个整数都在1到n之间(包括),不然我给出的示例就会出现索引越界了,这样就可以使用这个龟兔赛跑的算法,也有人管叫快慢指针,有重复就形成闭环:

def findDuplicate_ok(nums):
  tortoise=nums[0]
  hare=nums[0]
  while True:
    tortoise=nums[tortoise]#龟
    hare=nums[nums[hare]]#兔
    if tortoise==hare:
      break
  
  ptr1=nums[0]
  ptr2=tortoise
  while ptr1!=ptr2:
    ptr1=nums[ptr1]
    ptr2=nums[ptr2]
  return ptr1

arr1=[1,3,4,2,2]
arr3=[1,4,6,8,2,3,8,5,7]
print(findDuplicate_ok(arr1))#2
print(findDuplicate_ok(arr3))#8

时间复杂度:O(n),空间复杂度:O(1)

当然如果是初学者,会感觉到有点复杂,没关系,我们可以在龟(或兔或两者)的位置设置断点,然后步进,一步一步的看整个算法的执行流程就明白了,这个也是大家在需要进行调试或者了解一些变量的变化的最常见有效的方法。

不便调试的,我也将整个执行过程贴出来,方便观察:

数组:nums=[1,4,6,8,2,3,8,5,7]

第1次

第2次

第3次

第4次

第5次

nums[0]=1

nums[1]=4

nums[4]=2

nums[2]=6

nums[6]=8

nums[0]=1

nums[nums[1]]=2

nums[nums[2]]=8

nums[7]=5

nums[3]=8

当迭代到第5次的时候,两者相等了,于是就跳出循环,然后就通过指针找出重复的值

ptr1=1

nums[1]=4

nums[4]=2

nums[2]=6

nums[6]=8

ptr2=8

nums[8]=7

nums[7]=5

nums[5]=3

nums[3]=8


http://www.kler.cn/a/1988.html

相关文章:

  • iClient3D for Cesium 实现限高分析
  • vue2使用render,js中写html
  • macos 隐藏、加密磁盘、文件
  • 设计模式期末复习
  • 【QSS样式表 - ⑤】:QLineEdit控件样式
  • 多目标优化常用方法:pareto最优解
  • 【id:14】【20分】C. 字符串比较(指针与字符)
  • 强烈推荐:0基础入门网安必备《网络安全知识图谱》
  • 企业站项目
  • unordered系列的关联式容器介绍
  • 计算机网络复习重点
  • ChatGPT4已经来了,30秒做一个弹球游戏!
  • 8个python自动化脚本提高打工人幸福感~比心~
  • 今年好像没有金三银四了?
  • Pandas 与 PySpark 强强联手,功能与速度齐飞
  • map和set的使用指南
  • 电脑技巧:常见的浏览器内核介绍
  • Cookie和Session详解
  • 基于YOLOv5的疲劳驾驶检测系统(Python+清新界面+数据集)
  • PCL 使用ICP点云拼接
  • 如何监控和诊断JVM堆内和堆外内存使用?
  • 简单三步解决动态规划难题,记好这三步,动态规划就不难
  • 图神经网络的数学原理总结
  • JavaSE思维导图——总结篇
  • 前端已死?后端已亡?弯弯绕绕,几分真几分假
  • HCIE-Cloud Computing LAB备考第二步:逐题攻破--第五题:规划--根据网络平面规划表,完成ensp中接入交换机SW1/2的配置