leetcode-142-环形链表

142 环形链表

解法 1

遍历链表,同时使用一个 set 存储已经访问过的节点,如果当前正在访问的节点存在于 set 中,则说明找到了换的入口。返回该节点。

1
2
3
4
5
6
7
8
9
10
11
12
13
function detectCycle(head: ListNode | null): ListNode | null {
const set = new Set<ListNode>();
let node = head;
while (node) {
if (set.has(node)) {
return node;
} else {
set.add(node);
node = node.next;
}
}
return null;
}

解法 2

假设起点到环的入口点的距离是 a,慢指针和快指针在环内相遇,慢指针在环内走过的距离是 b,环内剩下的距离是 c,则环的周长是 b+c。
快指针走过的距离是慢指针的 2 倍。

1
2
3
4
5
slow * 2 = fast
slow = a + b
fast = a + b + (b + c)
2 * (a + b) = a + b + (b + c);
a = c

可以推导出环内剩余路程 c,和 a 距离相等。因此定义一个指针从 head 出发,慢指针继续走,相遇点即为入口点。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
function detectCycle(head: ListNode | null): ListNode | null {
let slow = head;
let fast = head;

while (fast && fast.next) {
slow = slow.next;
fast = fast.next.next;

if (slow === fast) {
break;
}
}

// 没有环
if (!fast || !fast.next) return null;

// 有环
let p = head;
while (p !== slow) {
p = p.next;
slow = slow.next;
}

return p;
}