leetcode 142 链表有环2

131 阅读1分钟

解法一:暴力法

思路:遍历列表,将每个节点加入map中,key为链表每个元素,值为true,判断链表元素是否在map中出现过,出现有环,否则无环

复杂度: 时间复杂度O(n), 空间复杂度O(n)

有点:好理解

var detectCycle = function(head) {
    let map = new Map() // 用于存储列表每个元素
    while(head && head.next) {
        if (map.has(head)) {
            return head
        }
        map.set(head, true)
        head = head.next
    }
    return null
};

解法二: 快慢指针

思路:创建一个快指针fast和一个满指针slow,快指针一次走两步,慢指针一次走一步。当慢指针到达入环点时,设此时所走的路程为a, 快指针已经走了n圈,慢指针开始走环,假设快慢指针在入环长度为b点处与快指针相遇,则快指针走的路程为a + n(b + c) + b, 是慢指针 a+b 的 2倍 , a + n(b + c) + b = 2 (a + b) 得出 a = c + (n -1) (b + c), 假设 n = 1, 则 a = c, 此时 新建一个star指针从头部开始以慢指针的速度走,star指针和slow指针在入环处相遇

image.png

复杂度: 时间复杂度O(n), 空间复杂度O(1)

var detectCycle = function(head) {
    let fast = slow = head
    if (!head) return head
    while(fast && fast.next) {
        fast = fast.next.next
        slow = slow.next
        if (fast === slow) {
            let star = head
            while (slow !== star) {
                star = star.next
                slow = slow.next
            }
            return star
        }
    }
    return null
};