简单LeetCode 141动画补充中引导学习
环形链表
快慢指针:有环必相遇
快慢指针同时从头出发:慢指针每次走一步、快指针每次走两步;如果有环,快指针会先进环并在环里追上慢指针。
时间复杂度 O(n)空间复杂度 O(1)
题单:面试热题
题目描述
给定一个链表,判断链表中是否存在环。要求只使用常数级额外空间。
学习目标
能说清快慢指针为什么必然相遇,并写对快指针的非空检查。
已完成 0 / 6 阶段
诊断
先问:为什么不能用集合
用 Set 记录走过的节点,能判环吗?题目要求常数空间,这个方案差在哪?
建议先完成当前阶段(提示 / 检查 / 自评),再进入下一步;也可以直接跳过。
解题思路
核心思想
快慢指针同时从头出发:慢指针每次走一步、快指针每次走两步;如果有环,快指针会先进环并在环里追上慢指针。
为什么需要它
用哈希表记录走过的节点也能判环,但要多花 O(n) 空间——题目要求常数空间,暗示需要一种"不用记"的判法。
第一反应:直觉方案
遍历时用集合记住每个走过的节点,再次遇到说明有环。正确,但费空间。
关键洞察
关键洞察是"相对速度":快指针每轮比慢指针多走一步,两者一旦都进入环,距离每轮缩短 1——只要距离有限,必然相遇(环再长也一样)。如果无环,快指针会先走到终点。这是"追及问题"的经典物理直觉,也是所有快慢指针题的底层逻辑。
时间复杂度 O(n)空间复杂度 O(1)
易错点
- 循环条件要同时检查 fast 和 fast.next——快指针一次跳两步,两个都必须非空,否则会空指针
- 慢指针必须先走再比较(或与快指针同起点、循环内先走)——如果都在起点就比,会立刻"相遇"
- 相遇说明有环,但相遇点不是环的入口(找入口是进阶题 142)
参考代码
参考代码
1function hasCycle(head) {
2 let slow = head, fast = head;
3 while (fast && fast.next) {
4 slow = slow.next;
5 fast = fast.next.next;
6 if (slow === fast) return true; // 追上了,说明有环
7 }
8 return false; // 快指针走到尽头,无环
9}
逐步演示
这道题目前是索引版:题面、解题思路与双语言代码已是完整内容; 逐步动画会按计划补充。