Prompt
Given an array that should contain consecutive numbers from 1 to N but is missing some, return the missing numbers in order. Empty input returns [].
Solution
This is a set-difference problem: expected values (1..N) minus actual values. The pattern shows up everywhere reconciliation happens — missing IDs in a sequence, unsynced records, gap detection. The efficient shape: pour the actual values into a Set for O(1) membership, then walk the expected range asking has. O(n) time, O(n) space.
The naive version replaces the Set with arr.includes(n) inside the loop — that's a linear scan per candidate, O(n²) total. It's the most common hidden-quadratic in JavaScript interviews because includes reads like a primitive operation. The rule: membership test inside a loop → hash it first. Same fix, every time.
Two guards worth pointing at:
Math.max(...[])is-Infinity— spreading an empty array into Math.max returns the identity for max, and the loop bound goes nonsensical. The early return isn't decorative. (For very large arrays, spread also risks blowing the argument limit;reducefor the max is the robust spelling.)- Deriving N from
Math.max(...arr)assumes the last number isn't missing — that's the stated contract here ("1 to N"), but restating an assumption you're relying on is a senior habit.
The classic variant: exactly one missing number can be found with no Set at all — expected sum N(N+1)/2 minus actual sum, O(1) space. Offer it when asked to optimize.
Red flag: includes inside the loop — O(n²) — and skipping the empty-array guard so the function returns garbage on [] instead of [].
Say it: "Set difference: hash what I have, walk 1..N with O(1) lookups — and if exactly one number were missing, the arithmetic-sum trick finds it in O(1) space."