数据结构-链表带环问题 #经典题#

本文解析了如何通过定义快慢指针判断链表是否存在环,并详细探讨了如何确定环的入口点。通过逻辑推导和数学分析,展示了如何利用快指针每次走2步或3步的策略找到环首节点。关键步骤包括设置慢速指针每次前进一位,快速指针每次前进两步,当两者相遇时,环首节点可由相遇位置追溯得出。
摘要由CSDN通过智能技术生成

一、问题描述

给定一个链表,返回链表开始入环的第一个节点。 如果链表无环,则返回 null。在这里插入图片描述
其中pos为圆环的入口点序号,但返回值并不是用pos,返回节点地址。

二、如何判断链表是否带环

假设链表带环,那么这个链表就会一直循环下去;假设这个链表没有环,那么这个链表最终就会走到空。基于此,我们定义两个指针(快慢指针),fast与slow。循环一直往后走,当fast为空或者fast->next为NULL时,代表无环;当fast==slow时,即相遇,即有环。

#fast和slow每次走几步合适#
在这里插入图片描述

slow很明显每次只走一步最合适,那么fast该走几步,是否一定能相遇?
首先,当fast进环时,slow走到了L的中点。如下图:
在这里插入图片描述

此后,fast开始转圈圈,当slow开始进环,fast可能在环内任意一点。然后fast开始追逐slow。(思考:为什么在slow的一圈之内,fast必追上slow?)
如果fast一次走2步,fast和slow必能一圈之内相遇。因为速度差为1,他们之间的距离每次缩减1,所以必能相遇。

如果fast一次走3步,这里就要分情况讨论:
在这里插入图片描述此时fast和slow相距C-X,距离依次减小:
第一圈:
C-X
C-X-2
C-X-4

0或者-1
当走到最后一步为0,则能相遇;为-1,代表反超,错过。即C-X为偶数时能相遇,否则不能。继续考虑第二圈是否能追上。

第二圈:
在这里插入图片描述此时fast比slow快1,距离为C-1。此时按每步距离减2
C-1
C-3
C-5

0/-1
同理,当最后一步为0,则能相遇;为-1,代表反超,错过,而此次错过则为永远错过。(因为接下来距离又会变成C-1)。所以当C-1为偶数时,第二圈能遇见,否则,永远不可能相遇。

三、如何求进环点

1、这里先给出结论:
在这里插入图片描述
如图所示,假设meet为相遇点,则一个指针从head开始走,一个指针从meet开始走,一定会在进环点相遇。接下来给出证明。

2、结论证明:
在这里插入图片描述相遇时slow走的距离:L+X
fast走的距离:NC+L+X
有NC+L+X = 2(L+X)----->L = NC-X ------>L = (N-1)C+C-X
注意:这里N代表N圈,由于不知道圈C和L的大小,所以无法判断在相遇前,fast转了多少圈。
L = (N-1)C+C-X 可知两指针head和meet必会在进环口相遇。

四、代码实现

struct ListNode *detectCycle(struct ListNode *head) 
{
    struct ListNode* slow = head;
    struct ListNode* fast = head;
    while(fast && fast->next)     //fast和fast->next的顺序不能反
    {                             //不然就会出现访问空指针的情况
        slow = slow->next;
        fast = fast->next->next;
        if(fast == slow)         //有环
        {
            struct ListNode* meet = fast;   //相遇点
            while(meet != head)
            {
                meet = meet->next;
                head = head->next;
            }
            return meet;
        }
    }
    return NULL;
}

五、总结

该题主要考察的逻辑推导能力,和数学找规律类似,读者重心应该放在推导上。该题代码量较少,对大家来说都不是问题,特别注意我代码里面的备注。

tip:写的不好的希望大家补充指正,出现争论,一定是你对。

评论 9
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小猿桥

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值