解法一:暴力法
思路:遍历列表,将每个节点加入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指针在入环处相遇
复杂度: 时间复杂度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
};