检测链表环

判断链表是否有环的两种方法

问题

给定一个链表,判断链表中是否存在环。如果存在环,返回 true;否则返回 false

解答

定义链表节点

class ListNode {
  constructor(val) {
    this.val = val;
    this.next = null;
  }
}

方法一:哈希表

function hasCycle(head) {
  // 用 Set 存储访问过的节点
  const visited = new Set();
  let current = head;

  while (current !== null) {
    // 如果当前节点已访问过,说明有环
    if (visited.has(current)) {
      return true;
    }
    visited.add(current);
    current = current.next;
  }

  return false;
}

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

function hasCycle(head) {
  if (head === null || head.next === null) {
    return false;
  }

  let slow = head; // 慢指针,每次走一步
  let fast = head; // 快指针,每次走两步

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

    // 快慢指针相遇,说明有环
    if (slow === fast) {
      return true;
    }
  }

  return false;
}

测试代码

// 创建有环链表:1 -> 2 -> 3 -> 4 -> 2(回到节点2)
const node1 = new ListNode(1);
const node2 = new ListNode(2);
const node3 = new ListNode(3);
const node4 = new ListNode(4);

node1.next = node2;
node2.next = node3;
node3.next = node4;
node4.next = node2; // 形成环

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

// 创建无环链表:1 -> 2 -> 3
const a = new ListNode(1);
const b = new ListNode(2);
const c = new ListNode(3);
a.next = b;
b.next = c;

console.log(hasCycle(a)); // false

关键点

  • 哈希表法:时间 O(n),空间 O(n),用 Set 记录访问过的节点
  • 快慢指针法:时间 O(n),空间 O(1),快指针每次走两步,慢指针每次走一步
  • 相遇原理:如果有环,快指针一定会追上慢指针;如果无环,快指针会先到达 null
  • 边界处理:空链表或只有一个节点且无环时直接返回 false