Floyd判圈算法

Floyd判圈算法,又称快慢指针算法、龟兔赛跑算法,是一个可以在有限状态机、迭代函数或者链表上判断是否存在环,求出该环的起点与长度的算法。

如果有限状态机、迭代函数或者链表上存在环,那么从同一个起点(即使这个起点不在某个环上)同时开始以不同的速度前进,2个指针最终相遇,那么可以判定存在一个环,且可以求出2者相遇所在的环的起点、环的长度。

算法描述:初始状态下,假设已知某个起点为结点S。现设两个指针slow、fast,将它们均指向S,接着,同时让slow指针、fast指针向前推进但是二者的速度不同,每次,slow指针前进1步,fast指针前进2步,一直循环,直至以下2种情况出现

1)fast指针无法前进,不存在环

2)slow、fast两指针相遇,存在环

这里以上图中的有环链表举例,其中S为链表起点,P为链表中环的入口点,M为快指针fast、慢指针slow的相遇点,设点S、点P之间的距离是m,在环中按顺时针方向,从点P到点M所需经过的距离为n,设环的周长是n

算法的时间复杂度:

当slow指针到达环入口点P时,最多走一圈,就会与fast指针相遇,两者从出发到相遇耗时相同,这里不妨以slow指针做为研究对象,slow指针的速度恒定,则slow指针从起点S到相遇点M的时间复杂度为O(m+n),是线性时间的算法

算法的空间复杂度:

这里需要创建起点指针S、环入口指针P、相遇点指针M等。空间复杂度为O(1)。

求环的长度

上述算法已经判断是否有环,可以在上述算法的基础之上,求出环的长度。

在fast指针与slow指针相遇在M点后,令fast指针不动,slow指针继续按原来速度前进,并统计其走过的距离,当其再次走到M点时,其走过的距离即为环的长度

求环的入口

在上述链表中S点与P点之间的长度为m,P点按顺时针方向到M点的距离为n,M点按顺时针方向到P点的距离为o,slow指针进入环之后,至多走一圈,就会和fast指针相遇,则相遇时slow指针走过的距离为 m+n,fast指针走过的距离为  m+n+N*(n+o),这里,n+o 即为环的周长,在fast指针、slow指针相遇时,fast指针比slow指针多走N个环(N>=1),2 * (m+n) = m+n+N*(n+o)

化简之后,可得 m = o + (N-1) * (n+o)

由上式可知,如果在起点S处、相遇点M点分别放置一个指针,让两指针以相同的速度(每次1步)向前走,当两指针相遇时,相遇点即为环入口点

在Floyd判圈算法中,判断是否有环是算法的第一步,环的入口点P、相遇点M均在环上,通过P点、M点中的任意一点均可求出环的长度(算法类似)

使用Floyd判圈算法的具体解题实例,可参考LeetCode141.环形链表LeetCode457.环形数组是否存在循环

这里可使用判断算法的题目的几种形式列举一下

1)判断单链表中是否有环,链表中的1个结点存储着下一个结点的地址

2)判断环形数组是否存在循环,根据数组中的每个元素的下标、元素值,可推出该元素下一个元素的下标(位置)

3)x_{0} = 1, x_{i+1} = f(x_{i}) ,使用单链表存储该数列,求循环节的起始位置以及循环节的长度

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值