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; }
|