程序员

单链表带环问题归纳总结

作者:admin 2021-08-20 我要评论

单链表的带环问题 判断单链表中是否存在环 1.问题分析 2.代码实现 若带环求环的长度 1.问题分析 2.代码实现 若带环求环的连接点 问题分析 2.代码实现 判断单链表...

在说正事之前,我要推荐一个福利:你还在原价购买阿里云、腾讯云、华为云服务器吗?那太亏啦!来这里,新购、升级、续费都打折,能够为您省60%的钱呢!2核4G企业级云服务器低至69元/年,点击进去看看吧>>>)

判断单链表中是否存在环

1.问题分析

(1)不带环的链表的最后一个结点的next指针是指向NULL,而带环链表没有类似的最后节点,所以无法判断带环链表的结束,也就无法通过遍历一遍链表来求取链表的长度。但是如果有一个指针在遍历时它最后会一直在环中重复打圈。因此我们可以使用快慢指针来判断(fast / slow)。如果链表带环那么当fast走到空指针时slow还未走到,他们不会相遇;当链表带环,那么当fast在环中一定会和slow相遇。
(2)慢指针slow向前一步,快指针fast应该向前几步呢?我们需要仔细分析。
情况一
假设慢指针走一步,快指针走两步:
当slow刚要进环时,fast和slow之间相差N个结点。每一次slow走一步,fast走两步,fast都在追slow,并且每追一次两者之间距离都会缩小1,最后一定会变成0(两者相遇)。
在这里插入图片描述
情况二
假设慢指针走一步,快指针走三步:
当N为偶数时,快慢指针会第一次就相遇。当N为奇数时,第一次快慢指针会恰好错过。这时候又分为两种情况。
1、当环的长度为偶数时:slow和fast之间的距离又变成奇数了,所以还会恰好错过,一直循环,无法相交
2.当环的长度为奇数时:slow和fast之间的距离变为偶数,则下次两者一定会相遇。

其余情况都会遇到与情况二相似的问题!!
在这里插入图片描述

在这里插入图片描述

2.代码实现

bool hasCycle(struct ListNode *head) {
    struct ListNode* slow = head, *fast = head;
    while(fast && fast->next)
    {
        fast = fast->next->next;
        slow = slow->next;
        if(fast == slow)
            return true;
    }
    return false;
}

若带环,求环的长度

1.问题分析

在上一个问题中,我们已经求得了快慢指针相遇的点,若让快慢指针自此从相遇点开始走,则再次相遇时,快指针比满指针多走的长度就是环的长度,同时,由于快指针每次比慢指针多走一步,所以多走的长度 = 慢指针走的长度 = 两个指针走的次数

2.代码实现

int CircleLong main()
{
    fast = slow = meet   //先将两个指针都定位在相遇点
    int count = 0;       //用于计数
    while(fast != slow)
    {
        fast = fast->next->next; 
        slow = slow->next;
        count++;
    }
    return count;
}

若带环,求环的连接点

问题分析

由定理:相遇点meet到环连接点的距离 = 头指针到连接点的距离。
所以我们让两个指针(正常指针,每次都走一步)分别从相遇点和头指针位置走,两个指针相遇的结点就是环的连接点。 证明如下:
在这里插入图片描述

2.代码实现

struct ListNode *detectCycle(struct ListNode *head) {
    struct ListNode* slow = head, *fast = head;  //初始化快慢指针
    while(fast && fast->next)       //当fast走到空,或者fast的下一个走到空,都是快指针遍历完链表
    {
        fast = fast->next->next;    //fast每次走两步
        slow = slow->next;          //fast每次走一步
        if(fast == slow)  //相遇
        {
            struct ListNode* meet = fast;
            while(meet != head)
            {
                meet = meet->next;      //从相遇点开始
                head = head->next;      //从头指针开始
            }
            return meet;           //返回连接点
        }
    }
    return NULL;  //没有相遇返回空指针
}

;原文链接:https://blog.csdn.net/cdzg_zzk/article/details/115916613

版权声明:本文转载自网络,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。本站转载出于传播更多优秀技术知识之目的,如有侵权请联系QQ/微信:153890879删除

相关文章
  • 单链表带环问题归纳总结

    单链表带环问题归纳总结

  • 和阿里P8大佬面试互怼了半小时的Fork/J

    和阿里P8大佬面试互怼了半小时的Fork/J

  • 初步认识C Lesson 2

    初步认识C Lesson 2

  • TCP ,你丫的终于来了!!!

    TCP ,你丫的终于来了!!!

腾讯云代理商
海外云服务器