First Missing Positive
Given an unsorted integer array nums
Example 1
Output: 3
Example 2
Output: 2
Example 3
Output: 1
How to Think About It
Step 1: The answer is between 1 and n + 1
With n numbers, the best case is that they are exactly 1, 2, ..., n, and then the answer is n + 1. Any gap makes the answer smaller. So values below 1 or above n can never matter.
Step 2: Give each useful value its own slot
If every value vv - 1inums[i] != i + 1
Step 3: Place values by swapping (cyclic sort)
For each index inums[i]nums[i] - 1
Step 4: Why it is still O(n)
Each swap puts one value in its final slot for good, so there are at most n swaps in total, however the loops are nested.
Walkthrough
nums = [3, 4, -1, 1]
| At index | Swap | Array after |
|---|---|---|
| 0 | 3 to slot 2 | [-1, 4, 3, 1] |
| 0 | -1 is out of range: stop | [-1, 4, 3, 1] |
| 1 | 4 to slot 3 | [-1, 1, 3, 4] |
| 1 | 1 to slot 0 | [1, -1, 3, 4] |
| 2, 3 | already in place | [1, -1, 3, 4] |
Index 1 does not hold 2, so the answer is 2.
Java Solution
The check nums[nums[i] - 1] != nums[i]
public class FirstMissingPositive {
public static int firstMissingPositive(int[] nums) {
int n = nums.length;
// Put every value v in 1..n at index v - 1 (cyclic sort)
for (int i = 0; i < n; i++) {
while (nums[i] >= 1 && nums[i] <= n && nums[nums[i] - 1] != nums[i]) {
int target = nums[i] - 1;
int tmp = nums[target];
nums[target] = nums[i];
nums[i] = tmp; // the value that was there gets placed next
}
}
for (int i = 0; i < n; i++) {
if (nums[i] != i + 1) {
return i + 1; // the first slot without its value
}
}
return n + 1; // 1..n are all present
}
public static void main(String[] args) {
System.out.println(firstMissingPositive(new int[] {1, 2, 0})); // 3
System.out.println(firstMissingPositive(new int[] {3, 4, -1, 1})); // 2
System.out.println(firstMissingPositive(new int[] {7, 8, 9, 11, 12})); // 1
}
}
The original implementation,
Complexity
- Time: O(n).
- Space: O(1); the array is rearranged in place.
Marking slots by sign instead of swapping is the trick in