LeetCode-141.环形链表

haiweilian2021-03-13算法LeetCode

题目描述

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

如果链表中有某个节点,可以通过连续跟踪 next 指针再次到达,则链表中存在环。 为了表示给定链表中的环,我们使用整数 pos 来表示链表尾连接到链表中的位置(索引从 0 开始)。 如果 pos-1,则在该链表中没有环。注意:pos 不作为参数进行传递,仅仅是为了标识链表的实际情况。

如果链表中存在环,则返回 true 。 否则,返回 false

示例 1:

示例

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

示例 2:

示例

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

示例 3:

示例

输入:head = [1], pos = -1
输出:false
解释:链表中没有环。

进阶:

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

解法一集合记录

使用集合记录已经遍历过的节点,如果再次遍历到那么它就是一个环形链表

  1. 记录可以使用 ArraySet 等数据结构,只要能存储就可以了。
  2. 在遍历的时候如果集合里没有这个节点就存储进去;如果有这个节点,证明再次遍历到了这个节点,那么它就是一个环形链表。

代码实现

由于使用空间保存了每个节点,这时的空间复杂度 O(n)。

/**
 * @param {ListNode} head
 * @return {boolean}
 */
var hasCycle = function (head) {
  // 创建一个集合记录
  let cache = new Set();
  while (head) {
    // 如果已经存在,证明已经遍历过一次了,那么它就是一个环形链表。
    if (cache.has(head)) {
      return true;
    } else {
      cache.add(head);
    }
    head = head.next;
  }
  return false;
};

// ===================================================================
// ========================== @test ==================================
// ===================================================================
let ListNode = {
  val: 1,
  next: {
    val: 2,
    next: {
      val: 3,
      next: null,
    },
  },
};
ListNode.next.next.next = ListNode.next;

console.log(hasCycle(ListNode)); // true

解法二之快慢指针

如果是一个圆,快指针最终都会追上慢指针

如操场跑步,一个人跑的快(fast)、一个人跑的慢(slow),迟早跑的快的会追上跑的慢的(多跑了一圈)。

  1. 首先快的和慢的都是从起点出发的。快的跑两步,慢的跑一步。
  2. 如果快的会先到达终点,证明不是一个环形。
  3. 如果两者会再次相遇(节点相等),证明是一个环形。

代码实现

没有使用额外的空间,这时空间复杂度 O(1)。

/**
 * @param {ListNode} head
 * @return {boolean}
 */
var hasCycle = function (head) {
  let fast = head;
  let slow = head;
  // 如果快的到达终点,那么它不是一个环形链表。
  while (fast && fast.next) {
    // 快的跑两步
    fast = fast.next.next;
    // 慢的跑一步
    slow = slow.next;
    // 如果快的追上了慢的,那么它就是一个环形链表。
    if (fast === slow) {
      return true;
    }
  }
  return false;
};
// @lc code=end

// ===================================================================
// ========================== @test ==================================
// ===================================================================
let ListNode = {
  val: 1,
  next: {
    val: 2,
    next: {
      val: 3,
      next: null,
    },
  },
};
ListNode.next.next.next = ListNode.next;

console.log(hasCycle(ListNode)); // true
最后更新时间 1/13/2024, 4:55:28 AM