1. Problem Summary
You are given an integer array nums.
Your task is to find the smallest positive integer (greater than 0) that does not appear in the array.
Important characteristics:
- The number must be positive (1, 2, 3, …)
- The array may contain:
- negative numbers
- zeros
- duplicates
- large numbers beyond range of interest
- The required answer must be computed in:
- O(N) time
- O(1) extra space
Example interpretation:
For input [3, 4, -1, 1], the smallest missing positive is 2.
2. Key Insights
The answer is always in the range [1 … N+1]
Given array length = N:
- If array contains all numbers from 1 to N, then answer is N+1
- Otherwise, the missing number is within [1, N]
Ignoring irrelevant values
Numbers that are:
- ≤ 0
- greater than N
cannot contribute to the missing result.
Use array indices as hash markers
We map value v to index v - 1.
If value exists, we mark its presence inside the array itself.
In-place marking method
To mark presence, we flip numbers to negative (or maintain sign).
Final scan identifies missing positive
The first index with a positive value indicates the missing number.
3. Approach
Step-by-step Strategy
Step 1: Replace invalid values
Convert all values ≤ 0 or > N to a placeholder (e.g., N+1)
Step 2: Mark presence
For each value v in array:
index = abs(v) - 1
if index in range:
mark nums[index] as negative (if not already)
Step 3: Find first missing positive
Scan from index 0 onward:
- first index i with positive value → answer = i + 1
Step 4: If all marked
Return N + 1
4. Time and Space Complexity
Time Complexity: O(N)
- Single pass normalize
- Single pass mark
- Single pass detect
Space Complexity: O(1)
- In-place marking
- No extra data structures
5. Java Solution
class Solution {
public int firstMissingPositive(int[] nums) {
int n = nums.length;
// Step 1: Clean values outside range
for (int i = 0; i < n; i++) {
if (nums[i] <= 0 || nums[i] > n) {
nums[i] = n + 1;
}
}
// Step 2: Mark presence using index
for (int i = 0; i < n; i++) {
int val = Math.abs(nums[i]);
if (val >= 1 && val <= n) {
int index = val - 1;
if (nums[index] > 0) {
nums[index] = -nums[index];
}
}
}
// Step 3: Find first positive index
for (int i = 0; i < n; i++) {
if (nums[i] > 0) {
return i + 1;
}
}
// Step 4: All present
return n + 1;
}
}
6. Dry Run Examples
Example 1
Input:
nums = [1, 2, 0]
Step 1 cleanup:
[1, 2, 3] // 0 replaced with n+1 (3)
Step 2 marking:
- mark index 0 → [-1, 2, 3]
- mark index 1 → [-1, -2, 3]
- 3 out of range → ignore
Step 3 scan:
index 2 is positive → answer = 3
Output:
3
Example 2
Input:
nums = [3, 4, -1, 1]
Step 1 cleanup:
[3, 4, 5, 1]
Step 2 marking:
- val=3 → mark index 2 → [3, 4, -5, 1]
- val=4 → mark index 3 → [3, 4, -5, -1]
- val=5 ignored
- val=1 → mark index 0 → [-3, 4, -5, -1]
Step 3 scan:
index 1 is positive → answer = 2
Output:
2
Example 3
Input:
nums = [7, 8, 9, 11, 12]
Step 1 cleanup:
[6, 6, 6, 6, 6] // all replaced
Step 2 marking:
none in range, nothing changes
Step 3 scan:
index 0 positive → answer = 1
Output:
1
Example 4
Input:
nums = [1, 2, 3, 4]
Process results in all marked → answer = N+1 = 5
Output:
5
7. Why This Solution Works
- Restricts search space to realistic bounds
- Uses array itself as presence map
- Marks only valid values
- Exactly matches O(N) and O(1) constraints
- Avoids sorting or hash sets
- Mathematically proven correctness
8. Common Mistakes
- Sorting the array (O(N log N), fails constraints)
- Using HashSet (extra space, fails constraints)
- Ignoring negative or zero effects
- Off-by-one indexing errors
- Returning 0 (answer must be ≥ 1)
