LeetCode笔记——141环形链表

题目:

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

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

思路:我本来自己想的是在环形链表中。每一个节点的下一个节点都不可能为空。若为空的话返回false;若不为空的话,继续循环,知道循环次数等于链表的个数。实际上链表中的节点个数并不已知,所以该方法不可以。然后就直接看了leetcode中的解答,有两种思路,如下;

思路1:使用哈希表

创建hashset存放节点。如果节点已经存在,则存在环;若节点不存在放入set中。

(引用leetcode)我们遍历所有结点并在哈希表中存储每个结点的引用(或内存地址)。如果当前结点为空结点 null(即已检测到链表尾部的下一个结点),那么我们已经遍历完整个链表,并且该链表不是环形链表。如果当前结点的引用已经存在于哈希表中,那么返回 true(即该链表为环形链表)。

复杂度分析(引用leetcode)

  • 时间复杂度:O(n), 对于含有 nnn 个元素的链表,我们访问每个元素最多一次。添加一个结点到哈希表中只需要花费 O(1) 的时间。

  • 空间复杂度:O(n), 空间取决于添加到哈希表中的元素数目,最多可以添加 n 个元素(这种解法是不是使用了额外空间?)

public class Solution {
    public boolean hasCycle(ListNode head) {
      Set hashset=new HashSet<>();
    ListNode tem=head;
        while(tem!=null)
        {
            if(hashset.contains(tem))
            {
                return true;
            }
            else
            {
               hashset.add(tem);
            }
            tem=tem.next;
        }
        return false;
        
    }
}

思路2 :快慢指针

这种思路 比较巧妙。使用两种快慢指针,快指针每次走两步,慢指针每次走一步。对于无环链表,快指针先到达链表末尾,对于有环链表,快指针总会追上满指针。

复杂度分析(引用leetcode)

  • 时间复杂度:O(n), 让我们将 nnn 设为链表中结点的总数。为了分析时间复杂度,我们分别考虑下面两种情况。

    • 链表中不存在环:
      快指针将会首先到达尾部,其时间取决于列表的长度,也就是 O(n)。

    • 链表中存在环:
      我们将慢指针的移动过程划分为两个阶段:非环部分与环形部分:

      1. 慢指针在走完非环部分阶段后将进入环形部分:此时,快指针已经进入环中 迭代次数=非环部分长度=N\text{迭代次数} = \text{非环部分长度} = N迭代次数=非环部分长度=N

      2. 两个指针都在环形区域中:考虑两个在环形赛道上的运动员 - 快跑者每次移动两步而慢跑者每次只移动一步。其速度的差值为1,因此需要经过 二者之间距离速度差值\dfrac{\text{二者之间距离}}{\text{速度差值}}​速度差值​​二者之间距离​​ 次循环后,快跑者可以追上慢跑者。这个距离几乎就是 "环形部分长度 K\text{环形部分长度 K}环形部分长度 K" 且速度差值为 1,我们得出这样的结论 迭代次数=近似于\text{迭代次数} = \text{近似于}迭代次数=近似于 "环形部分长度 K\text{环形部分长度 K}环形部分长度 K".

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

  • 空间复杂度:O(1), 我们只使用了慢指针和快指针两个结点,所以空间复杂度为 O(1)。

public class Solution {
    public boolean hasCycle(ListNode head) {
      if(head==null||head.next==null)
          return false;
        ListNode slow=head;
        ListNode quick=head.next;
        while(slow!=quick)
        {
            if(quick==null||quick.next==null)
            {
                return false;
            }
            else
            {
                slow=slow.next;
                quick=quick.next.next;
            }
        }
        return true;
    }
}

你可能感兴趣的:(LeetCode笔记)