返回

LeetCode141: 寻找环形链表

前端

LeetCode 中的 141 题考察了算法的基本概念之一:寻找环形链表。环形链表是一种数据结构,其中链表的最后一个节点指向链表中的另一个节点,形成一个闭合回路。本指南将深入探讨 LeetCode 141 题,教你使用 JavaScript 轻松解决问题。

理解问题

LeetCode 141 题提供了一个链表 head,要求我们确定链表中是否存在环。如果存在环,我们需要返回环的入口节点;如果不存在环,则返回 null。

算法流程

1. 使用快慢指针:

  • 初始化两个指针:快指针 fast 和慢指针 slow,两者均指向链表头。
  • while 快指针和慢指针都不为 null:
    • 将快指针向前移动两步,即 fast = fast.next.next
    • 将慢指针向前移动一步,即 slow = slow.next
  • 如果在任何时候快指针和慢指针相遇,则表明链表中存在环。

2. 查找环入口:

  • 如果 fast 和 slow 相遇,则链表中存在环。
  • 将慢指针重置为链表头,并继续移动慢指针和快指针,每次移动一步。
  • 当慢指针和快指针再次相遇时,它们将位于环的入口。

代码示例

const hasCycle = (head) => {
  if (!head || !head.next) {
    return false;
  }

  let fast = head;
  let slow = head;

  while (fast && fast.next) {
    fast = fast.next.next;
    slow = slow.next;

    if (fast === slow) {
      return true;
    }
  }

  return false;
};

const findCycleEntrance = (head) => {
  if (!hasCycle(head)) {
    return null;
  }

  let slow = head;
  let fast = head;

  while (fast && fast.next) {
    slow = slow.next;
    fast = fast.next.next;

    if (slow === fast) {
      slow = head;

      while (slow !== fast) {
        slow = slow.next;
        fast = fast.next;
      }

      return slow;
    }
  }

  return null;
};

复杂度分析

  • 时间复杂度:O(n),其中 n 是链表中的节点数。快慢指针方法在最坏情况下需要遍历整个链表。
  • 空间复杂度:O(1),因为我们只使用了常数数量的额外空间。

结论

LeetCode 141 题要求判断链表中是否存在环,并返回环的入口节点。我们使用快慢指针方法来高效地解决这个问题。本指南提供了详细的解释和清晰的代码示例,帮助你掌握寻找环形链表背后的原理。