当前位置:   article > 正文

【链表】【证明】快慢指针判断链表有环、寻找环入口、计算环大小的原理_快慢指针判断是否成环

快慢指针判断是否成环

问题:

        给定一个链表
        1. 判断链表是否有环。
        2. 如果链表有环,请找出环入口。
        3. 计算环的大小。

思路:快慢指针

        分别定义一个快指针fast和慢指针slow,快指针一次走两步,慢指针一次走一步。如果链表没有环,那么fast最终会指向nullptr;如果链表有环,那么快指针和慢指针最终会相遇。所以,如果最终fast == nullptr,那么判断链表无环;如果最终fast == slow,且fast != nullptr,那么链表有环。

证明如下。

1. 第一步:快慢指针从头结点出发。如下图所示。蓝色表示快指针fast,红色表示慢指针slow。
这里写图片描述

2. 第二步:慢指针slow走到了环入口,共走了k步。此时快指针fast越过了环入口的步数为delta。因为快指针可能绕着环走了很多圈,所以有k == delta + n * R,其中R为环的大小,n为快指针绕环走的步数。
这里写图片描述

3. 第三步:慢指针进入环中。因为快指针每次都比慢指针快一步,所以,快慢指针最后一定会相遇。【证明了必然会相遇。

4. 第四步:计算快慢指针相遇位置。因为慢指针在刚进入环时距离快指针delta步,所以快指针还需要比慢指针多走R - delta步才能与慢指针相遇。又因为快指针每次走两步,所以快指针还需要走2(R - delta)步。那么,相遇位置为2(R - delta) + delta == 2R - delta,即,距离环入口delta处,与慢指针刚进入环时快指针所在位置对称。
这里写图片描述

5. 第五步:快指针重新从头结点开始走,速度为一次一步,与慢指针相同。可知,快指针走到环入口时,所需步数为k。刚好,k == delta + n * R,这也是慢指针在环中所走的距离。由快慢指针在环中的相遇位置可知,慢指针此时刚好走到了环入口,并与快指针相遇,此时,找到了环入口。【证明了能找到环入口。
这里写图片描述

6. 第六步:如何求环大小。这个相对简单,在证明链表是否有环的过程中,快慢指针第一次相遇。此后,快指针继续按一次两步的速度走,慢指针按一次一步的速度走,并设置一个计数器count = 0,每走一次加1,。当快慢指针再次相遇时,快指针刚好比慢指针多走了R步,而计数器count == R。【计算了环大小

核心代码

寻找环入口

LLNode * LinkedList::entranceOfLoop()
{
    LLNode * slow = pHead;
    LLNode * fast = pHead;

    while(fast && fast->pNext)
    {
        fast = fast->pNext->pNext;
        slow = slow->pNext;
        if(fast == slow) break;
    }

    if(!fast || !fast->pNext) return nullptr;

    fast = pHead;
    while(fast != slow)
    {
        fast = fast->pNext;
        slow = slow->pNext;
    }

    return fast;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23

计算环大小

int LinkedList::sizeOfLoop()
{
    LLNode * slow = pHead;
    LLNode * fast = pHead;

    while(fast && fast->pNext)
    {
        fast = fast->pNext->pNext;
        slow = pNext;
        if(fast == slow) break;
    }

    if(!fast || !fast->pNext) return 0;

    int size = 1;
    fast = fast->pNext->pNext;
    slow = slow->pNext;
    while(fast != slow)
    {
        ++size;
        fast = fast->pNext->pNext;
        slow = slow->pNext;
    }

    return size;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26

测试

        功能测试:未进行功能测试。
        边界值测试:未进行边界值测试。
        特殊输入测试:未进行特殊输入测试。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/喵喵爱编程/article/detail/895252
推荐阅读
相关标签
  

闽ICP备14008679号