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?

这题比较经典,首先判断是否有环,这个就是快慢指针。第二步找环的入口,找到一个较好的解释。

/*  
    我们可以使用两枚指针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. 大家可以自行思考整个圈的情况是否如此.
*/
/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    ListNode *detectCycle(ListNode *head) {
        ListNode *fast = head, *slow = head, *node = NULL;

        bool iscyc = false;
        while(fast && fast->next)
        {
            slow = slow->next;
            fast = fast->next->next;
            if(slow == fast)
            {
                iscyc = true;
                node = slow;
                break;
            }            
        }

        if(iscyc == false)
            return NULL;
        while(node != head)
        {
            node = node->next;
            head = head->next;
        }
        return node;

    }
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值