zoukankan      html  css  js  c++  java
  • Floyd判圈算法

    转载自http://www.tuicool.com/articles/bi63ei

    问题:如何检测一个链表是否有环,如果有,那么如何确定环的起点.

    龟兔解法的基本思想可以用我们跑步的例子来解释,如果两个人同时出发,如果赛道有环,那么快的一方总能追上慢的一方。进一步想,追上时快的一方肯定比慢的一方多跑了几圈,即多跑的路的长度是圈的长度的倍数。

    基于上面的想法,Floyd用两个指针,一个慢指针(龟)每次前进一步,快指针(兔)指针每次前进两步(两步或多步效果是等价的,只要一个比另一个快就行,从后面的讨论我们可以看出这一点)。如果两者在链表头以外的某一点相遇(即相等)了,那么说明链表有环,否则,如果(快指针)到达了链表的结尾,那么说明没环。

    环的检测从上面的解释理解起来应该没有问题。接下来我们来看一下如何确定环的起点,这也是Floyd解法的第二部分。方法是将慢指针(或快指针)移到链表起点,两者同时移动,每次移动一步,那么两者相遇的地方就是环的起点。

    假设起点到环的起点距离为m,已经确定有环,环的周长为n,(第一次)相遇点距离环的起点的距离是k。那么当两者相遇时,慢指针移动的总距离为i,i = m + a * n + k,因为快指针移动速度为慢指针的两倍,那么快指针的移动距离为2i,2i = m + b * n + k。其中,a和b分别为慢指针和快指针在第一次相遇时转过的圈数。我们让两者相减(快减慢),那么有i = (b - a) * n。即i是圈长度的倍数。利用这个结论我们就可以理解Floyd解法为什么能确定环的起点。将一个指针移到链表起点,另一个指针不变,即距离链表起点为i处,两者同时移动,每次移动一步。当第一个指针前进了m,即到达环起点时,另一个指针距离链表起点为i + m。考虑到i为圈长度的倍数,可以理解为指针从链表起点出发,走到环起点,然后绕环转了几圈,所以第二个指针也必然在环的起点。即两者相遇点就是环的起点。 

    实例程序如下:

     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 }

    之后的面试中问到如何确定环的长度。当然,如果在确定环的起点后再跑一圈就可以,但这样就小题大作了。在确定有环后,再让快的和慢的指针跑一圈,再次追上后,快的比慢的正好多跑一圈,这就求出了环的长度。

  • 相关阅读:
    【网易官方】极客战记(codecombat)攻略-游戏开发1-漫游者危险
    【网易官方】极客战记(codecombat)攻略-游戏开发1-军事训练
    【网易官方】极客战记(codecombat)攻略-游戏开发1-取舍
    【网易官方】极客战记(codecombat)攻略-游戏开发1-碾碎它
    【网易官方】极客战记(codecombat)攻略-游戏开发1-斩首老鼠
    课程报名 | 5G时代的视频云服务关键技术与实践
    干货 | 京东云账号安全管理最佳实践
    这大概是今年介绍云原生最清晰明了的文章!
    “大促”背后的技术 | 当我们说促销的时候,我们在谈什么?
    技术沙龙 | 从高并发架构到企业级区块链探索零售创新
  • 原文地址:https://www.cnblogs.com/FuTaimeng/p/5308631.html
Copyright © 2011-2022 走看看