141.环形链表——哈希表、快慢指针(js)

45 阅读2分钟

题目描述

leetcode 141.环形链表

解题思路

哈希表

依次遍历链表中的所有节点,并将 节点(即它的内存地址) 存入 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
};