Rearrange the array in place so every useful number points to its own home slot, then read the first empty home.
Every positive x ≤ n belongs in slot x − 1; the first slot that breaks that rule is the answer.
The answer cannot be larger than n + 1. That means the only values worth organizing are 1 through n; negatives, zeros, and oversized values can be ignored.
Each frame mirrors one swap or one invariant check in the code. Green slots already contain their home value; the final cyan slot marks the first gap.
def firstMissingPositive(nums):
n = len(nums)
# Put each useful value x into slot x - 1.
for i in range(n):
while 1 <= nums[i] <= n and nums[nums[i] - 1] != nums[i]:
target = nums[i] - 1
nums[i], nums[target] = nums[target], nums[i]
# The first slot that misses its home value is the answer.
for i, value in enumerate(nums):
if value != i + 1:
return i + 1
return n + 1
The inner loop may look nested, but every successful swap puts a value into its final home. Across the whole run, there are at most O(n) swaps.
1 ≤ x ≤ nOnly these values can change whether the answer is one of the first n positives.home(x) = x − 1When x reaches index x − 1, the array records that x exists without extra memory.nums[i] ≠ i + 1The scan stops at the first mismatch; every earlier positive has already been accounted for.After swaps, 1 sits at slot 0 while slot 1 cannot hold 2. The first gap is 2.
Slots 0 and 1 contain 1 and 2; the next positive, 3, is the first one missing.
I only care about values from 1 to n. I use each value as an address, swap it into its home slot, and then the first index i without i + 1 is the answer.