Linked List Cycle II

原题链接

问题:给定一个单向链表,若存在环,则返回环的其实结点,否则返回NULL。

在解这个问题之前,先看个数学问题,或者是体育现象,我们都知道马拉松比赛,运动员需要在体育场外跑一段距离,然后进入体育场跑道。如下草图


设运动员在场外需要跑的路段AB长为k,环形跑道的周长为c,跑道的入口为B,进入后沿跑道顺时针方向跑,现有选手甲乙,乙每秒跑1千米,甲更生猛,每秒跑2千米(有的看官可能会骂:扯淡,你当火箭啊),这不蜗牛都称急速蜗牛了,都跟赛车比赛了,体谅体谅,理解理解。假设甲在距离入口B x 远的D处与乙相遇,那么我们看看k 和 x有什么关系。

甲肯定先到圈里进行循环,等待着乙进入到环里,当乙进入后,甲就有机会追上乙,不会给乙跑完一整圈的机会。

到甲乙相遇的时候,我们知道,甲比乙多跑的距离是环周长的整数倍,而且甲的速度是乙的二倍,跑过的路程同样是乙的两倍。



最后的等式k = mc + x,结合图示我们知道,若此时甲从A重新出发向着B前进,乙从D出发,沿着环路前进,速度相同,那么要么乙没用绕圈就与甲在B相遇,要么绕了几圈后与甲在B相遇,这取决于k与c的关系,若k远大于c那么乙就不的不在环路循环,以等待甲。

好了,这问题就明了了,为了找到环路的起始点,我们利用判断环路存在的方法来得到首次相遇的结点,然后调整两个指针的步长,使其相等,然后一个在相遇点继续走,一个回到出发点重新走,则二者再次相遇的位置就是环路的起始点。


//CODE

class Solution {
public:
    ListNode *detectCycle(ListNode *head) {
        if(head == NULL || head->next == NULL)
         return NULL;
        ListNode *pfast, *pslow;
        pfast = pslow = head;
        //
        while(pfast && pfast->next)//notice condition
        {
            pfast = pfast->next->next;
            pslow = pslow->next;
            if(pfast == pslow) break;
        }
        if(pfast != pslow)
        return NULL;
        pfast = head;
        //
        while(pfast != pslow)
        {
            pfast = pfast->next;
            pslow = pslow->next;
        }
        return pfast;
    }
};


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值