• LeetCode之“链表”:Linked List Cycle && Linked List Cycle II


    1.Linked List Cycle

      题目链接

      题目要求:

      Given a linked list, determine if it has a cycle in it.

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

      刚看到这道题,很容易写出下边的程序:

     1 bool hasCycle(ListNode *head) {
     2     ListNode *a = head, *b = head;
     3     while(a)
     4     {
     5         b = a->next;
     6         while(b)
     7         {
     8             if(a == b)
     9                 return true;
    10             b = b->next;
    11         }
    12         a = a->next;
    13     }
    14     
    15     return false;
    16 }

      这个程序最大的问题在于“死循环”,例如在下边这种情况就会进入死循环:

      

      要解决这个问题,我们可以定义两个指针slow、fast,slow每次前进一步,fast每次前进两步。如果链表存在环,则在循环一定次数后,slow与fast一定会重合(找个例子推导下就明白了)。具体从程序如下:

     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     bool hasCycle(ListNode *head) {
    12         if(head == nullptr || head->next == nullptr)
    13             return false;
    14         
    15         ListNode *slow = head, *fast = head;
    16         while(fast != nullptr && fast->next != nullptr)
    17         {
    18             slow = slow->next;
    19             fast = fast->next->next;
    20             if(slow == fast)
    21                 return true;
    22         }
    23         
    24         return false;
    25     }
    26 };

    2.Linked List Cycle II

      题目链接

      题目要求:

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

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

      这道题难度还是挺大的。具体解法参考自一博文

      首先看图:

       

      从链表起始处到环入口长度为:a,从环入口到Faster和Slower相遇点长度为:x,整个环长为:c。

       假设从开始到相遇,Slower走过的路程长为s,由于Faster的步速是Slower的2倍,那么Faster在这段时间走的路程长为2s。

       而对于Faster来说,他走的路程还等于之前绕整个环跑的n圈的路程nc,加上最后这一次遇见Slower的路程s。

       所以我们有:

                       2s = nc + s 

       对于Slower来说,他走的路程长度s还等于他从链表起始处到相遇点的距离,所以有:

                        s = a + x 

       通过以上两个式子代入化简有:

                        a + x = nc

                        a = nc - x

                        a = (n-1)c + c-x

                        a = kc + (c-x)

      那么可以看出,c-x,就是从相遇点继续走回到环入口的距离。上面整个式子可以看出,如果此时有个pointer1从起始点出发并且同时还有个pointer2从相遇点出发继续往前走(都只迈一步),那么绕过k圈以后, pointer2会和pointer1在环入口相遇。这样,换入口就找到了。

      具体程序如下:

     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         ListNode* slow = head;
    13         ListNode* fast = head;
    14         while (true){
    15             if(!fast || !fast->next)
    16                 return nullptr;
    17             
    18             slow = slow->next;
    19             fast = fast->next->next;
    20             if (slow == fast)
    21                 break;
    22         }
    23         
    24         slow = head;
    25         while (slow != fast){
    26             slow = slow->next;
    27             fast = fast->next;
    28         }
    29         return slow;
    30     }
    31 };
  • 相关阅读:
    C#读写INI配置文件(转)
    关于DBNull
    XNA项目运行错误:No suitable graphics card found.
    C#3.0新增特性
    Windows 8 Metro开发疑难杂症(三)——导航(2),数据保存,数据虚拟化
    Windows 8 Metro开发疑难杂症(一)——导航
    windows 8 metro 风格开发(7)发布一个常用控件类库
    Windows 8 Metro开发疑难杂症(四)——(伪)数据库
    windows 8 metro 风格开发(9)Interactive(Behavior和EventTrigger)
    Windows 8 Metro开发疑难杂症(六)——APP的挂起状态
  • 原文地址:https://www.cnblogs.com/xiehongfeng100/p/4601182.html
Copyright © 2020-2023  润新知