Leetcode-142.环形链表II(龟兔赛跑算法)

如有想看算法具体分析请看
龟兔赛跑算法逻辑分析

在这里插入图片描述
上一题
Leetcode-141.环形链表
已经分析了是否链表中会存在一个环结构。
这道题依然会使用龟兔赛跑算法。
但并不是与上一题一样。会继续对算法进行拓展。

题目要求,要找到环的入口,这就比上一道题要恶心多了。

继续要使用快慢指针。

fast=fast->next->next;//一次走两个结点
slow=slow->next;//慢指针一次走一个结点

为什么还要使用快指针一次走两个结点的方法呢?
想找环的入口的结点,则必须要先证明有环,才能找结点。在不确定有环的情况下去找结点,明显不科学。而诺快指针走两个结点,慢指针走一个结点更符号题目测试用例的变化。若使用其他方法,容易不确定是否有环。

slow刚入环
设线(环外)的结点数位T(即slow走T次就到环的入口结点)
在这里插入图片描述

两指针相差N个结点,相当于fast在slow的后面L-N个结点

当两指针相遇时
在这里插入图片描述
相遇时,慢指针走了X个结点。且,这必是在慢指针一圈之内相遇的。
设环有L个结点。

为什么两指针相遇的点是慢指针在一圈之内?
因为fast的速度是slow的两倍,这其实就是追击问题。且,每次两指针的运动之差为1,所以是不可能错过的。如果这是slow在第二圈的时候相遇的,那么快指针早已在这时间段走完两圈了。就凭这个,所以只能是一圈之内的。

因为,因为fast是slow的两倍,所以,每循环一次,两者距离就缩小1,从某种意义上,就相当于,快指针每次走一个结点,而慢指针不动。最后会在L-N次移动后两指针重合。
则,他们两,fast与slow在环中走了L-(L-N)个节点,也就是N个节点。

且fast在环中走的N个结点,就相当于slow在环外走的T个结点。

则对于slow而言,只要再走L-(L-N)==N个结点就到达环的入口结点。因为先前推出fast只要走L-N次循环就能相遇,且slow也要走L-N次。
在这里插入图片描述
我们不知道环有多大,也不知道fast走了多少圈,但是,fast始终只走两个结点。如果fast走了多圈,即T会远大于L,
但对其弱化后,和fast走一圈是一个层次的意思。

即可推出T ==N。

在这里插入图片描述

即slow走N个结点,等于fast一次一个结点从头结点开始走,当两者相遇的结点,就是环的入口。

代码实现

struct ListNode *detectCycle(struct ListNode *head)
{
    struct ListNode* fast=head,*slow=head;
    while(fast&&fast->next)//第一次在环中相遇
    {
        fast=fast->next->next;
        slow=slow->next;
        if(fast==slow)
        {
            fast=head;
            while(fast!=slow)//负责第二次相遇也就是环的头结点
            {
                fast=fast->next;
                slow=slow->next;
            }
            return fast;
        }
    }
    return NULL;

    
}

感谢各位大佬观看,如有问题,烦请指点一二。谢谢。

  • 7
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值