跳到主要内容

怎么判断链表有环?

可以使用以下几种方法来判断链表是否有环:

一、哈希表法

  1. 原理:遍历链表,将每个节点的地址存储在哈希表中。如果在遍历过程中遇到一个节点的地址已经在哈希表中出现过,那么说明链表存在环。
  2. 实现步骤:
    • 创建一个哈希表,用于存储节点的地址。
    • 从链表的头节点开始遍历链表。
    • 对于每个节点,检查其地址是否已经在哈希表中。如果是,则说明链表有环;如果不是,将该节点的地址加入哈希表。
    • 继续遍历下一个节点,直到遍历完整个链表。
  3. 优点:实现简单,时间复杂度为 $O(n)$,其中 $n$ 是链表的长度。
  4. 缺点:需要额外的空间来存储哈希表。

二、快慢指针法(Floyd 判圈算法)

  1. 原理:使用两个指针,一个慢指针每次移动一步,一个快指针每次移动两步。如果链表存在环,那么快指针一定会在某个时刻追上慢指针。
  2. 实现步骤:
    • 创建两个指针,慢指针和快指针,初始时都指向链表的头节点。
    • 慢指针每次移动一步,快指针每次移动两步。
    • 如果在遍历过程中,快指针到达了链表的末尾(即快指针为 null),则说明链表没有环。
    • 如果在遍历过程中,快指针和慢指针相遇,则说明链表存在环。
  3. 优点:不需要额外的空间,时间复杂度为 $O(n)$,其中 $n$ 是链表的长度。
  4. 缺点:实现相对复杂一些。

例如,以下是使用快慢指针法判断链表是否有环的代码示例(以 Java 语言为例):

class ListNode {
int val;
ListNode next;
ListNode(int x) {
val = x;
next = null;
}
}

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

总之,哈希表法和快慢指针法都可以有效地判断链表是否有环。在实际应用中,可以根据具体情况选择合适的方法。