题目描述
解题思路
哈希表
依次遍历链表中的所有节点,并将 节点(即它的内存地址) 存入 Set 中。如果链表存在环,则某个节点会被 访问两次 ,即指针会指向已经存在于 Set 中的节点。因此,我们可以利用 Set 来判断链表是否为环形链表: 如果当前访问的节点已经存在于 Set 中,则说明链表存在环;否则将该节点存入Set中然后继续遍历,直到遍历完整个链表。
为什么选择Set,而不是Map?
Set(集合):用于存储
唯一的元素,可以快速查重。
Map(映射):用于存储键值对(key-value),适用于需要存储额外信息的情况。
快慢指针
快指针(fast) 从头节点出发,每次移动 两步;慢指针(slow) 从头节点出发,每次移动 一步。如果链表是 环形链表,则快指针会在某个时刻追上慢指针(即二者指向同一个节点);反之,如果链表 无环,则快指针会先到达链表的 null 位置,永远无法与慢指针相遇。
完整代码
哈希表代码
var hasCycle = function(head) {
// 哈希表
let set = new Set()
while (head) { // 当链表还有元素没有被遍历时
if (set.has(head)) { // 如果当前访问的节点已经存在于 Set 中
return true // 说明链表存在环
}
else {
set.add(head) // 否则将该节点存入Set中
head = head.next // 然后继续遍历
}
}
return false // 遍历完整个链表,无环,返回false
};
快慢指针代码
var hasCycle = function(head) {
// 快慢指针
let slow = head
let fast = head
while (fast && fast.next) {
fast = fast.next.next // 一次移动两步
slow = slow.next // 一次移动一步
if (fast === slow) return true // 快慢指针指向同一个节点,说明存在环
}
return false
};