主题
复盘 · LC 141 环形链表(三刷)
题目
- 题号:LeetCode 141
- 名称:环形链表(Linked List Cycle)
- 难度:Easy
- 链接:leetcode.cn/problems/linked-list-cycle
- 今日代码:
141-环形链表-三刷/index.js
题意
给定链表头 head,判断是否存在环:某个节点的 next 能再次回到先前出现过的节点。有环返回 true,否则 false。
- 空链、单节点无环都是
false。 - 进阶:尽量 O(1) 额外空间。
边界:无环走到 null;环在尾部;整条都是环;单节点自环。
涉及算法
| 标签 | 一句话 |
|---|---|
| 哈希 / 打标 | 走过的节点放进 Set(或改节点字段),再遇即有环 |
| 快慢指针(Floyd) | slow 走一步、fast 走两步,能相遇则有环 |
教程对照:13 · 链表进阶(环检测、相交、合并)。
评价我的解法
相对 8/4 二刷 的 isVisit 打标,今天已切到快慢指针,方向对了。
我的代码(摘自 141-环形链表-三刷/index.js,不含本地测例):
javascript
var hasCycle = function (head) {
if (!head) {
return false;
}
if (!head.next) {
return false;
}
let fast = head;
let slow = head;
let isFind = false;
while (true) {
if (fast.next && fast.next.next) {
fast = fast.next.next;
} else {
break;
}
if (slow.next) {
slow = slow.next;
} else {
break;
}
if (fast === slow) {
console.log(fast, slow);
isFind = true;
break;
}
}
return isFind;
};1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
主流程正确(提交 29/29):快两步、慢一步,相遇则有环;无环时 fast 撞到尽头就 break。
- 时间 O(n),空间 O(1)——相对二刷的改节点打标,这才是面试模板。
- 糙点:
while (true)+ 层层if (fast.next && fast.next.next)比标准写法啰嗦,易漏边界。- 提交代码里还留着
console.log,面试/正式提交都应去掉。 isFind可直接return true/return false,少一层状态。
建议默写成「条件写在 while 上」的紧凑版,和 142 共用同一套骨架。
最佳题解
javascript
/**
* @param {ListNode} head
* @return {boolean}
*/
var hasCycle = function (head) {
if (!head || !head.next) return false;
let slow = head;
let fast = head;
while (fast && fast.next) {
slow = slow.next;
fast = fast.next.next;
if (slow === fast) return true;
}
return false;
};1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
2
3
4
5
6
7
8
9
10
11
12
13
14
15
- 时间 O(n),空间 O(1)。
- 为何更优:循环条件直接表达「快指针还能走两步」;无额外标志位、无调试输出;和 142 的第一阶段完全同构。
关联题目
| 题 | 为何相关 |
|---|---|
| 142. 环形链表 II | 相遇后找环入口,今天同日已做 |
| 160. 相交链表 | 双指针「路程对齐」同一家族 |
| 876. 链表的中间结点 | 快慢指针找中点,节奏相同 |
一句话带走
141:快慢同起跑,快两慢一能相遇即有环——三刷已上模板,下一步把 while 条件写干净。
