链表环检测算法(LeetCode 141)

我的实现方法:哈希表检测法
原始思路
通过哈希表记录已访问过的节点,当遍历到已存在的节点时,说明存在环
初始代码
1
2
3
4
5
6
7
8
9
|
var hasCycle = function (head) {
let seen = new Map()
while(head){
seen.set(head, true);
head = head.next;
if(seen.get(head)) return true
}
return false
};
|
代码优化建议
- 数据结构优化:
Map
→ Set
更适合存储唯一值
- 逻辑顺序调整:先检查再移动指针更严谨
优化后代码
1
2
3
4
5
6
7
8
9
|
var hasCycle = function(head) {
const seen = new Set();
while (head) {
if (seen.has(head)) return true; // 先检查当前节点
seen.add(head); // 再记录访问状态
head = head.next; // 最后移动指针
}
return false;
};
|
问题分析
原始代码存在两个潜在风险:
- 检查的是
head.next
而非当前节点
- 移动指针后可能跳过最后一个节点的检查
扩展方法:快慢指针法(Floyd判圈算法)
核心思想
使用速度不同的双指针:
- 快指针每次走两步
- 慢指针每次走一步
- 若存在环则必然相遇
代码实现
1
2
3
4
5
6
7
8
9
|
var hasCycle = function(head) {
let slow = head, fast = head;
while (fast && fast.next) {
slow = slow.next;
fast = fast.next.next;
if (slow === fast) return true;
}
return false;
};
|
对比分析
方法 |
时间复杂度 |
空间复杂度 |
适用场景 |
哈希表检测法 |
O(n) |
O(n) |
需要记录访问路径的场景 |
快慢指针法 |
O(n) |
O(1) |
空间敏感型场景 |