链表的带环问题

最近在编程刷题网站力扣上刷了两道比较有意思的链表问题,一道是判断链表是否带环,另一道则是找到链表入环的开始节点。通过对此类带环问题的思考与学习,见识到该问题思想的巧妙,遂作此博客陈述其解题思路。

判断是否带环

首先是判断一个链表中是否带环,对于该问题我们可以通过使用快慢双指针的方法来解决。让fast指针的速度是slow指针的2倍:
在这里插入图片描述
假设当slow入环时,fast与slow的相距节点数为N:在这里插入图片描述

因为slow:fast=1:2,所以slow与fast同时前进时,每次距离N减1直至两指针相距为0时两指针相遇,即slow与fast的地址值相等,此时便可判断链表带环。而如果fast指针或fast->next指向NULL,则说明链表中不带环。具体代码实现如下:

typedef struct ListNode ListNode;
bool hasCycle(struct ListNode *head) {
    ListNode* slow, *fast;
    slow = fast = head;
    while (fast && fast->next)//若fast指针或fast->next指向NULL,则说明链表中不带环
    {
        slow = slow->next;
        fast = fast->next->next;
        if (slow == fast)
            return true;
    }
    return false;
}

但此外我们还应思考另一个问题,fast的速度若是slow的3、4乃至5倍时,fast与slow指针最终能否相遇呢?让我们先思考一下slow:fast=1:3的情况,这也就是说两指针距离N每次减2,若N为偶数那fast最终肯定可以追上slow。但N为奇数时第一次fast会到slow的前一个位置,此时,fast与slow的命运便由另一个量决定了,那便是环的节点数C。当fast到slow前面时,二者的距离N便变成了C-1,此时如果C为奇数,N便是偶数,fast就一定可以追上slow;而C为偶数时,fast便会重蹈之前的覆辙,又跑到了slow的前一个节点,最终如牛郎织女般永远无法相见。
但事实真就如此吗?实际不然,让我们回到slow一开始入环的时候:
在这里插入图片描述

然后让我们以数学的思维思考一下这个问题,fast与slow无法相遇的情况是当N为奇数同时C为偶数的时候。那么这两个条件是否可以同时存在呢?首先让我们假设slow此时与链表的头节点相距L个节点,并且fast已经绕环走了X圈,于是根据此时fast与slow的步数便有如下等式:
在这里插入图片描述

明显此时等式左边为偶数,如果N为奇数C为偶数,那么XC为偶数,C-N为奇数,最终等式右边为奇数。明显等式不成立。所以slow:fast=1:3时两指针最终必定可以相遇,可喜可贺,可喜可贺!

找出环的开始节点

判断了链表是否存在环之后,我们便可以找出环的开始节点。
在这里插入图片描述

此时,slow与fast指针指向同一个节点,由于slow:fast=1:2,此时slow走过的节点数必定小于C,然后可以得到他们相遇时的一个等式:
在这里插入图片描述
明显L的距离会等于fast与slow相遇节点到环开始节点的距离,因此我们便可以这样完成这道题:

typedef struct ListNode ListNode;
struct ListNode *detectCycle(struct ListNode *head) {
    ListNode* slow, *fast, *meet;
    slow = fast = head;
    while (fast && fast->next)
    {
        slow = slow->next;
        fast = fast->next->next;
        if (slow == fast)//存在环
        {
            meet = slow;
            while (head != meet)
            {
                head = head->next;
                meet = meet->next;
            }
            return meet;
        }
    }
    return NULL;//不存在环
}

可见,这两道链表带环问题对于代码很简单,但思维却较复杂。

  • 26
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值