LC 41: First Missing Positive. Rated Hard. Here's the problem statement:
Input: [3, 4, -1, 1]Output: 2Input: [1, 2, 0]Output: 3Given an unsorted integer array, find the smallest missing positive integer.
Must run in O(n) time and O(1) extra space. That constraint — constant space —
is what makes it Hard. You can't use a hash set. You can't sort with mergesort.
You need to rearrange the array in place.
But look at the first input: [3, 4, -1, 1]. The values 1, 3, and 4 are
positive integers with valid “home addresses” in an array of length 4. Value 1
belongs at index 0, value 3 belongs at index 2, value 4 belongs at index 3.
They're legitimate mail. The -1? That's junk mail — a negative number has no
home in our [1, n] mailroom. It should be ignored, not sorted.
The problem also mentions 0 (not positive, so junk) and values larger than n
(oversized packages — no mailbox exists for them). But once you filter out the
junk, what remains? Legitimate letters that know their home addresses. You already
know how to sort those. You already know how to scan for mismatches. You already
know every move. The only new idea is: skip the junk.
Which values CAN be placed using cyclic sort? Range is 14.
Here's the complete solution. Read it slowly — you've seen every piece before:
function firstMissingPositive(nums: number[]): number { const n = nums.length; // Step 1: Cyclic sort — place each value at its home for (let i = 0; i < n; i++) { while ( nums[i] > 0 && // not junk (negative/zero) nums[i] <= n && // not oversized (> n) nums[i] !== nums[nums[i] - 1] // not already home / duplicate ) { const home = nums[i] - 1; [nums[i], nums[home]] = [nums[home], nums[i]]; } } // Step 2: Scan for first mismatch for (let i = 0; i < n; i++) { if (nums[i] !== i + 1) return i + 1; } // All positions filled — answer is n + 1 return n + 1;}Three moves: filter, place, scan. The while condition has two extra
guards — nums[i] > 0 and nums[i] <= n — that skip junk mail and oversized
packages. The duplicate guard (nums[i] !== nums[nums[i] - 1]) is the same one
you learned in the previous lesson. The address formula (nums[i] - 1) is the
same one you discovered when you first placed values by hand. The scan is the
same mismatch scan, but this time you only care about the first missing value,
so you return immediately.
If every position 0 through n-1 holds its correct value, then the array is a
perfect permutation of [1, n] and the answer is n + 1 — the next positive
integer after the range.
You just solved a Hard problem with an idea you discovered by sorting five numbers. The address formula, the settle loop, the duplicate guard, the mismatch scan — every piece was built one lesson at a time. That's the power of cyclic sort: one core insight, layered incrementally, solving problems from Easy to Hard.