zoukankan      html  css  js  c++  java
  • Leetcode 141.环形链表

    环形链表

    给定一个链表,判断链表中是否有环。

    进阶:
    你能否不使用额外空间解决此题?

    通过使用具有 不同速度 的快、慢两个指针遍历链表,空间复杂度可以被降低至 O(1)O(1)O(1)。慢指针每次移动一步,而快指针每次移动两步。

    如果列表中不存在环,最终快指针将会最先到达尾部,此时我们可以返回 false。

    现在考虑一个环形链表,把慢指针和快指针想象成两个在环形赛道上跑步的运动员(分别称之为慢跑者与快跑者)。而快跑者最终一定会追上慢跑者。这是为什么呢?考虑下面这种情况(记作情况 A) - 假如快跑者只落后慢跑者一步,在下一次迭代中,它们就会分别跑了一步或两步并相遇。

    其他情况又会怎样呢?例如,我们没有考虑快跑者在慢跑者之后两步或三步的情况。但其实不难想到,因为在下一次或者下下次迭代后,又会变成上面提到的情况 A。

     

     1 public boolean hasCycle(ListNode head){
     2     if(head==null||head.next==null){
     3         return false;
     4     }
     5     ListNode slow=head;
     6     ListNode fast=head.next;
     7     while(slow!=fast){
     8         if(fast==null||fast.next==null){
     9             return false;
    10         }
    11         slow=slow.next;
    12         fast=fast.next.next;
    13     }
    14     return true;
    15 }

    复杂度分析

    • 时间复杂度:O(n)O(n)O(n), 让我们将 nnn 设为链表中结点的总数。为了分析时间复杂度,我们分别考虑下面两种情况。
      • 链表中不存在环:
        快指针将会首先到达尾部,其时间取决于列表的长度,也就是 O(n)O(n)O(n)。
      • 链表中存在环:
        我们将慢指针的移动过程划分为两个阶段:非环部分与环形部分:
        • 慢指针在走完非环部分阶段后将进入环形部分:此时,快指针已经进入环中 迭代次数=非环部分长度=N ext{迭代次数} = ext{非环部分长度} = N迭代次数=非环部分长度=N
        • 两个指针都在环形区域中:考虑两个在环形赛道上的运动员 - 快跑者每次移动两步而慢跑者每次只移动一步。其速度的差值为1,因此需要经过 二者之间距离速度差值dfrac{ ext{二者之间距离}}{ ext{速度差值}}速度差值二者之间距离 次循环后,快跑者可以追上慢跑者。这个距离几乎就是 "环形部分长度 K ext{环形部分长度 K}环形部分长度 K" 且速度差值为 1,我们得出这样的结论 迭代次数=近似于 ext{迭代次数} = ext{近似于}迭代次数=近似于 "环形部分长度 K ext{环形部分长度 K}环形部分长度 K".

      因此,在最糟糕的情形下,时间复杂度为 O(N+K)O(N+K)O(N+K),也就是 O(n)O(n)O(n)。

    • 空间复杂度:O(1)O(1)O(1), 我们只使用了慢指针和快指针两个结点,所以空间复杂度为 O(1)O(1)O(1)。
  • 相关阅读:
    Codeforces Round #436 (Div. 2)
    【bzoj1090】 [SCOI2003]字符串折叠
    【并查集】食物链(带权并查集)
    【图论】二分图
    【图论】关押罪犯
    关于图论的若干巴拉巴拉
    一系列的入门and一堆吐槽
    【分块】八
    9-30刷题记录
    bzoj5055
  • 原文地址:https://www.cnblogs.com/kexinxin/p/10189550.html
Copyright © 2011-2022 走看看