图解题库 / 链表 · 快慢指针

141. 环形链表

简单 含交互动画

学完这道你应该能: 说清它为什么用「快慢指针」,而不是死记步骤; 合上页面,自己默写出核心代码; 用 30 秒把思路讲清楚。

题目描述

判断链表中是否存在(某个节点的 next 指回了前面的节点)。

链表 = 3 → 2 → 0 → −4
= −4 的 next 指回 2
输出 = true

思路解析

你可以边走边把节点存进集合,如果遇到一个已经存过的,就有环——但要 O(n) 空间。更妙的是快慢指针(Floyd 判圈),只用 O(1) 空间。

两个指针都从头出发,fast 每次 2 步、slow 每次 1 步。没有环,fast 会先冲到 null(返回 false);有环,fast 进环后会一圈圈逼近 slow,每步缩短 1 的距离,最终在环里相遇

起点 · slow=fast=头:slowfast 都从头 3 出发。注意末尾 −4 的箭头是橙色回边「↺ 回到 2」——这就是环。

第 1 步 · slow→2, fast→0:slow 走 1 步到 2,fast 走 2 步到 0。两者都已进入环。

第 2 步 · fast 沿回边绕回 2:slow 到 0。fast 走两步:0 → −4 → 沿回边绕回 2,所以 fast 出现在 2 的位置(看着像“后退”,其实是绕了环一圈的一部分)。

第 3 步 · 相遇于 −4!:slow 到 −4;fast 走两步 2 → 0 → −4 也到 −4。两个指针相遇了!这证明链表有环,返回 true。

作为对比:如果链表没有环,fast 一路领先,会先走到链表末尾的 null。循环条件 while fast and fast.next 一旦不成立,就说明无环,返回 false。

Floyd 判圈(龟兔赛跑):进环后 fast 每步把和 slow 的距离缩短 1,绝不会“跳过”,所以一定相遇。找环的入口(142)、找重复数(287)都用它。

参考代码(Python)

Python
1slow = fast = head
2while fast and fast.next:           # 无环时这里会停
3    slow = slow.next                # 慢走 1
4    fast = fast.next.next           # 快走 2
5    if slow is fast: return True    # 相遇 = 有环
6return False                        # fast 到 null = 无环

复杂度分析

  • 时间复杂度:O(n) —— 有环时 fast 最多绕一圈追上
  • 空间复杂度:O(1) —— 两个指针,不用哈希

套路模板

记住骨架:快慢同出发、快2慢1、相遇即有环、fast到null即无环。要找环入口,就在相遇后再用一个指针从头与 slow 同速走,相遇点就是入口。

Python
1slow = fast = head
2while fast and fast.next:
3    slow, fast = slow.next, fast.next.next
4    if slow is fast: return True    # 相遇=有环
5return False

易错点

  • 用 slow.val == fast.val 判相遇 → ✅ 用 slow is fast 判同一节点(不同节点可能值相同,要比身份不比值)
  • 循环条件漏判 fast.next → ✅ while fast and fast.next(fast 跨两步前要确保中间节点存在)

以上文字与上方动画完全同一思路:先看动画建立直觉 → 读文字巩固 → 关掉页面自己默写一遍代码,能写出来才算真的掌握

下一题 →2. 两数相加 ← 返回题库