链表-141-环形链表

题目:

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

为了表示给定链表中的环,我们使用整数 pos 来表示链表尾连接到链表中的位置(索引从 0 开始)。 如果 pos 是 -1,则在该链表中没有环。

 

示例 1:

输入:head = [3,2,0,-4], pos = 1
输出:true
解释:链表中有一个环,其尾部连接到第二个节点。


示例 2:

输入:head = [1,2], pos = 0
输出:true
解释:链表中有一个环,其尾部连接到第一个节点。


 

进阶:

你能用 O(1)(即,常量)内存解决此问题吗?

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/linked-list-cycle
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

思路:哈希表和双指针法:

哈希表

把节点挨个放到哈希表中,如果链表中有环,则某个节点必然重复出现。用HashSet中的contains判定

代码如下:

/**
 * Definition for singly-linked list.
 * class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) {
 *         val = x;
 *         next = null;
 *     }
 * }
 */
public class Solution {
    public boolean hasCycle(ListNode head) {
        HashSet<ListNode> node=new HashSet<>(); //Hash表
        while(head!=null){
            if(node.contains(head)){
                return true;
            }
            else{
                node.add(head);
                head=head.next;
            }
        }
        return false;
    }
}

复杂度分析:

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

空间复杂度:O(n),空间取决于添加到哈希表中的元素数目,最多可以添加 n 个元素。

双指针

我们想成小学中的追及问题,当两个人在一个体育场跑步时,特别地当两个人的速度不一致时,这两个人在某一个时间必然相遇。所以我们可以设置一个快慢指针在链表上跑,当快慢指针指向同一个节点时必然有环;

代码如下:

/**
 * Definition for singly-linked list.
 * class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) {
 *         val = x;
 *         next = null;
 *     }
 * }
 */
public class Solution {
    public boolean hasCycle(ListNode head) {
      if(head==null || head.next==null){
          return false;
      }
      ListNode low =head;
      ListNode fast=head.next;
      while(low!=fast){
          if(fast==null || fast.next==null){  //这里主要为了防止下面fast=fast.next.next;出现空指针异常
              return false;
          }
          else{
              low=low.next;
              fast=fast.next.next;
          }
      }
      return true;
    }
}

复杂度分析:

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

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

近似于快指针多走了一圈环状部分

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

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

原文地址:https://www.cnblogs.com/Yunus-ustb/p/12891704.html