zoukankan      html  css  js  c++  java
  • [Leetcode] Linked list cycle ii 判断链表是否有环

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

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

    题意:给定链表,若是有环,则返回环开始的节点,没有则返回NULL

    思路:题目分两步走,第一、判断是否有环,第二若是有,找到环的起始点。关于第一点,可以参考之前的博客 Linked list cycle。这里主要分析在有环的情况下的第二步。

     

    说明:在环中的前进方向是顺时针,起点为X,环入口为Y,相遇点在Z;无环X->Y的距离(节点数)为a,相遇点Z到Y的距离为b,环长r。

    慢指针一次走一步,即slow=slow->next;快指针一次走两步,即fast=fast->next->next。第一相遇在Z点时,slow走过的距离为a+b,fast走过的距离为a+mr+b (m>=1),解释两个问题:一、为什么能遇到?二、为什么第一次相遇时,慢指针slow没有在环内走过n(0<n<m)圈?针对问题一,因为,快指针fast相对慢指针的的速度是1,即,可以看成,慢指针slow静止不动,而快指针fast以速度为1的情况下,在环内前行,所以能遇到。针对问题二,同样的道理,因为fast相对slow的速度是1,假设slow静止,则在fast以速度1完成一圈之前,肯定能遇到slow。

    下面分析相遇时,走过的距离,即结点数。slow:a+b;fast:2*(a+b);所以2*(a+b)=a+mr+b(m>=1),故得到a+b=mr,即a=mr-b;所以讲slow放在X点,fast了依旧在Z点,只不过fast的速度降为1,这样,当X到Y的时候,fast也到Y,即得到环的入口点。

     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     {
    13         
    14         ListNode *slow=head;
    15         ListNode *fast=head;
    16         //寻找第一个相遇点
    17         while(fast&&fast->next)
    18         {
    19             slow=slow->next;
    20             fast=fast->next->next;
    21             if(slow==fast)
    22                 break;
    23         }
    24         //不存在环
    25         if(fast==NULL||fast->next==NULL)
    26             return NULL;
    27         //存在环,slow从头开始,fast从相遇点开始单步走,再次相遇即环的开始点
    28         slow=head;
    29         while(slow !=fast)
    30         {
    31             slow=slow->next;
    32             fast=fast->next;
    33         }
    34         return slow;
    35     }
    36 };

    //参考了Cyberspace_TechNode的博客!!!

     相关问题的扩展:参考南京大乱炖

    1)环的长度是多少?

     方法一:从相遇点开始,让慢指针接着走,并计数,当慢指针slow和快指针再次相遇时,返回计数器的值就行

     方法二:第一次相遇后,让slow,fast继续走,记录到下次相遇时循环了几次。因为当fast第二次到达Z点时,fast走了一圈,slow走了半圈,而当fast第三次到达Z点时,fast走了两圈,slow走了一圈,正好还在Z点相遇。

    2)如何将有环的链表变成单链表(即解除环)?

    在本题的基础上,从环的入口开始,当指针的next为环的入口结点时,令next指向NULL即可。

  • 相关阅读:
    DOM优化
    jQuery绑定以及解除时间方法总结,以及事件触发的方法
    javascript的异步编程方法
    innerHTML,innertext ,textcontent,write()
    关于盒子的那些事
    关于HTTP的几种
    关于php中正则匹配包括换行符在内的任意字符的问题总结
    CSS透明属性详解
    Linux下apache日志分析与状态查看方法
    折半排序 (稳定的排序)
  • 原文地址:https://www.cnblogs.com/love-yh/p/7019976.html
Copyright © 2011-2022 走看看