zoukankan      html  css  js  c++  java
  • 142. Linked List Cycle II【easy】

    142. Linked List Cycle II【easy】

    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?

    解法一:

     1 /**
     2  * Definition for singly-linked list.
     3  * struct ListNode {
     4  *     int val;
     5  *     ListNode *next;
     6  *     ListNode(int x) : val(x), next(NULL) {}
     7  * };
     8  */
     9 class Solution {
    10 public:
    11     ListNode *detectCycle(ListNode *head) {
    12         if (head == NULL || head->next == NULL) {
    13             return NULL;
    14         }
    15         
    16         ListNode * slow = head;
    17         ListNode * fast = head;
    18         
    19         while (fast->next != NULL && fast->next->next != NULL) {
    20             slow = slow->next;
    21             fast = fast->next->next;
    22             
    23             if (fast == slow) {
    24                 return findNode(fast, head);
    25             }
    26         }
    27         
    28         return NULL;
    29     }
    30     
    31     ListNode * findNode(ListNode * fast, ListNode * head)
    32     {
    33         while (fast != head) {
    34             fast = fast->next;
    35             head = head->next;
    36         }
    37         
    38         return head;
    39     }
    40     
    41     
    42 };

    首先先看是否有环,有环的话我们要把其中一个指针移动到链表head节点,另外一个指针不变,然后这两个指针同时往前分别走一步,直到相等为止就是环的入口点;这个问题的算法证明如下:

     问题1:如何判断单链表中是否存在环(即下图中从结点E到结点R组成的环)?

            设一快一慢两个指针(Node *fast, *low)同时从链表起点开始遍历,其中快指针每次移动长度为2,慢指针则为1。则若无环,开始遍历之后fast不可能与low重合,且fast或fast->next最终必然到达NULL;若有环,则fast必然不迟于low先进入环,且由于fast移动步长为2,low移动步长为1,则在low进入环后继续绕环遍历一周之前fast必然能与low重合(且必然是第一次重合)。于是函数可写如下:

     1 bool hasCircle(Node* head, Node* &encounter)  
     2 {  
     3     Node *fast = head, *slow = head;  
     4     while(fast && fast->next)  
     5     {  
     6         fast = fast->next->next;  
     7         slow = slow->next;  
     8         if(fast == slow)  
     9         {  
    10             encounter = fast;  
    11             return true;  
    12         }  
    13     }  
    14     encounter = NULL;  
    15     return false;  
    16 }  

     问题2:若存在环,如何找到环的入口点(即上图中的结点E)?
           解答:如图中所示,设链起点到环入口点间的距离为x,环入口点到问题1中fast与low重合点的距离为y,又设在fast与low重合时fast已绕环n周(n>0),且此时low移动总长度为s,则fast移动总长度为2s,环的长度为r。则
            s + nr = 2s,n>0      ①
            s = x + y               ②
           由①式得  s = nr                 
           代入②式得
           nr = x + y
           x = nr - y                ③
           现让一指针p1从链表起点处开始遍历,指针p2从encounter处开始遍历,且p1和p2移动步长均为1。则当p1移动x步即到达环的入口点,由③式可知,此时p2也已移动x步即nr - y步。由于p2是从encounter处开始移动,故p2移动nr步是移回到了encounter处,再退y步则是到了环的入口点。也即,当p1移动x步第一次到达环的入口点时,p2也恰好到达了该入口点。于是函数可写如下:

     1 Node* findEntry(Node* head, Node* encounter)  
     2 {   
     3     Node *p1 = head, *p2 = encounter;  
     4     while(p1 != p2)  
     5     {  
     6         p1 = p1->next;  
     7         p2 = p2->next;  
     8     }  
     9     return p1;  
    10 }  

    另外一个解释也比较好:

    求解单链表环入口点的步骤:

    1:使用“指针追赶”方法找到相遇点(网上资料很多,此处略)。

    2:指针p1从链表头、p2从相遇点,同时出发,一次移动一个节点,再次的相遇点便是环的入口点。

    证明导向:p1从表头走,能与p2从相遇点走再次相遇,那么说明p1走到入口点时,p2可能刚好走了y-d(其中d是入口点与第一次相遇点的距离)个节点,或者走了几圈再加上y-d个节点。故就要找到y-d与x的关系。

    第一次相遇:S慢:表示一次移动一个节点的指针所走的路程(即节点个数)

                      S快:表示一次移动两个节点的指针所走的路程(节点个数)

                S慢 = x + d

                S快 = 2(x + d)

                S快 - S慢 = n倍y

                则有:x + d = ny

                      x = ny - d = (n - 1)y + (y - d)

        由此便说明了:x 个节点就相当于(n - 1)倍环周长加上y - d,正好是第一次相遇点到入口点的距离。

    证明参考自:

    http://blog.csdn.net/wuzhekai1985/article/details/6725263

    http://blog.sina.com.cn/s/blog_6a0e04380101a9o2.html

  • 相关阅读:
    word设置的密码忘了怎么办?
    Navicat Report Viewer 设置 HTTP 的方法
    如何处理Navicat Report Viewer 报表
    excel密码忘记了怎么办
    Beyond Compare文本比较搜索功能详解
    Popular Cows POJ
    Problem B. Harvest of Apples HDU
    网络流模型整理
    The Shortest Statement CodeForces
    Vasya and Multisets CodeForces
  • 原文地址:https://www.cnblogs.com/abc-begin/p/7666817.html
Copyright © 2011-2022 走看看