• 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

  • 相关阅读:
    pip python代码
    Saltstack module http 详解
    Saltstack module hosts 详解
    Saltstack module highstate_doc 详解
    Saltstack module hashutil 详解
    Saltstack module group 详解
    Saltstack module grains 详解
    Saltstack module grafana4 详解
    Saltstack module google_chat 详解
    Saltstack module gnome 详解
  • 原文地址:https://www.cnblogs.com/abc-begin/p/7666817.html
Copyright © 2020-2023  润新知