Leetcode ☞ 142. Linked List Cycle II ☆

142. Linked List Cycle II

My Submissions
Question
Total Accepted: 68780  Total Submissions: 218547  Difficulty: Medium

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.








我的AC,也是最直白的(6ms,最快一批):

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     struct ListNode *next;
 * };
 */
struct ListNode *detectCycle(struct ListNode *head) {
    struct ListNode *fast, *slow;
    fast = slow = head;
    
    while (fast && fast->next){
        slow= slow->next;
        fast = fast->next->next;
        if (fast == slow)
            break;
    }
    if (fast == NULL || fast->next ==NULL)
        return NULL;

    fast = head;
    while(fast != slow){
        slow= slow->next;
        fast = fast->next;
    }
    return slow;
}

简洁版:

struct ListNode *detectCycle(struct ListNode *head) {  
    struct ListNode *fast, *slow, *ans;  
    fast = slow = head;
    ans = NULL;
    
    while (fast && fast->next){  
        slow= slow->next;  
        fast = fast->next->next;  
        if (fast == slow){
            ans = head;  
            while(ans != slow){  
                slow = slow->next;  
                ans = ans->next;
            }
            break;//这个break很关键 别落
        }
    }  
    return ans;  
}



分析:

判断一个链表是否有环,有则返回环入口点,否则返回NULL。



H________A____B
         |____|
         D    C

slow从H走到A时,fast一定在环上某处C(或B或D)。设此时slow走过了HA=x,fast前方距环入口点距离CDA=y,环周长为r。

首先,slow在进入环后,走了不到一圈就在交点处和fast重合,为何肯定没有走完一圈?因为slow在进入环的时候,fast与其之间的距离(沿着行走方向)至多为r-1【此种情况是slow进入,在入口点时,fast刚好在入口点的下一个位置】,不可能超过r-1,因为环的大小也才只有r 。fast追赶slow,最多只需要走r-1步,因为每走一步,slow和fast的相对距离减小1,那么slow最多只走了r-1步,就是最多只经过了r-1个节点,不可能走完一圈。


当fast若与slow相遇时,slow肯定没有走遍历完链表,而fast已经在环内循环了n圈(1<=n)。

环长为r,起点到环入口点的距离为a,入口环与相遇点距离为x,相遇点再到入口处距离为y。

slow步数 = a+x

fast步数 = a + nr + x

fast是slow的二倍,则有:a+nr+x = 2*(a+x)

整理得nr = a+x,移项有:

a = nr - x

 = (n-1)r +(r-x)

 = (n-1)r + y

y为相遇点到环入口点的距离。由此可知,从链表头到环入口点等于(n-1)循环内环+相遇点到环入口点。
于是我们从链表头、相遇点 这两点分别设一个指针,每次各走一步,两个指针必定相遇,且相遇第一点为环入口点。


类似的解释:
|------ n ------|
H____h____A__c__Meet 
          |_____|r
          
在p2和p1第一次相遇的时候,假定p1走了n步,环路的入口是在h步的时候经过的,那么有
  p1走的路径: h+c = n;         c为p1和p2相交点,距离环路入口的距离
  p2走的路径: h+c+k*r = 2*n;    r为环路的周长,k是整数
显然,如果从h+c点开始,p1再走n步骤的话,还可以回到h+c这个点
同时p2从头开始走的话,经过n步,也会达到h+c这点
显然在这个步骤当中p1和p2只有前h步走的路径不同,所以当p1和p2再次重合的时候,必然是在链表的环路入口点上。


解析整理自:http://blog.chinaunix.net/uid-26448049-id-3046656.html

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值