LeetCode 142. Linked List Cycle II

Given a linked list, return the node where the cycle begins. If there is no cycle, return null.

Note: Do not modify the linked list.

Follow up:
Can you solve it without using extra space?

题意:给你一个链表,找到圈始点,如果没有圈,返回NULL
注意:不能更改链表
另外:能不能不使用额外的空间?(即空间复杂度为0(1))

/*  
    我们可以使用两枚指针oneStep、twoStep,每次分别移动12步,若存在圈,则两枚指针在第1234...n圈后终会相遇(我们并不知道会在第几圈相遇)
    整个圈:1 -> 2 -> 3 -> 1
    部分圈:1 -> 2 -> 3 -> 4 -> 5 -> 6 -> 7 -> 8 -> 9 -> 10 -> 11 -> 12 -> 13 -> 14 -> 15 -> 5(跟5相连,形成圈)
           |<--------s------->| |<----------------------------r------------------------>|
           |<--------------------k----------------------->|
           |<------------------------------------2k--------------------------------------  
                                 ------------------------>|
           我们假设链表头到圈始点长度为s,圈长度为r,移动两枚指针后,相遇时oneStep走了k步,twoStep则走了2k步:
           1. 我们知道相遇时twoStep比oneStep多走了n圈,(1)(2k - s) - (k - s) = nr  =>  k = nr  =>  k = r (n = 1)
              (注意:我们取n = 1,即twoStep比oneStep多走一圈,因为一旦相遇我们便知道了有圈)

            k = r 于是便有了下面这幅图:
    部分圈:1 -> 2 -> 3 -> 4 -> 5 -> 6 -> 7 -> 8 -> 9 -> 10 -> 11 -> 12 -> 13 -> 14 -> 15 -> 5(跟5相连,形成圈)
           |<--------s------->| |<----------------------------r------------------------>|        
           |<--------------------r----------------------->|
           |<------------------------------------2r--------------------------------------  
                                 ------------------------>|
           2. s(我们知道s就是我们要求的圈始点)怎么求呢?

           3. 眼尖的同学可能已经看出来了,没错 s + r = 链表总长度,我们再将oneStep或者twoStep移动s就会再次相遇!

           于是便有了下面这幅图:
    部分圈:1 -> 2 -> 3 -> 4 -> 5 -> 6 -> 7 -> 8 -> 9 -> 10 -> 11 -> 12 -> 13 -> 14 -> 15 -> 5(跟5相连,形成圈)
           |<--------s------->| |<----------------------------r------------------------>|        
           |<--------------------r----------------------->| |************* s ************|
           |<------------------------------------2r--------------------------------------  
                                 ------------------------>| |************* s ************|

          4. 现在我们让oneStep再次从head开始,oneStep和twoStep每次均移动一步,再次相遇就会在起始点咯!

          5. 大家可以自行思考整个圈的情况是否如此.
*/
ListNode *detectCycle(ListNode *head) {
    if(head == NULL) return NULL;

    ListNode *oneStep = head, *twoStep = head;
    bool isCycle = false;
    while(twoStep -> next != NULL && twoStep -> next -> next != NULL){
        oneStep = oneStep -> next;
        twoStep = twoStep -> next -> next;
        if(oneStep == twoStep){
            isCycle = true;
            break;
        }
    }
    if(!isCycle) return NULL;

    oneStep = head;
    while(oneStep != twoStep){
        oneStep = oneStep -> next;
        twoStep = twoStep -> next;
    }
    return oneStep;
}
  • 6
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值