32. First Missing Positive
Topic :
arrays
Difficulty :
hard
Problem Link :
problem statement
Given an unsorted integer array nums
, return the smallest missing positive integer.
You must implement an algorithm that runs in O(n)
time and uses constant extra space.
Example 1:
Input: nums = [1,2,0]
Output: 3
Explanation: The numbers in the range [1,2] are all in the array.
Example 2:
Input: nums = [3,4,-1,1]
Output: 2
Explanation: 1 is in the array but 2 is missing.
Example 3:
Input: nums = [7,8,9,11,12]
Output: 1
Explanation: The smallest positive integer 1 is missing.
Constraints:
1 <= nums.length <= 105
-231 <= nums[i] <= 231 - 1
solution
APPROACH 1: USING SORTING
TIME COMPLEXITY : O(NLOGN)+O(N)
SPACE COMPLEXITY: O(1)
import java.io.*;
import java.util.*;
class FirstMissingPositive_using_Sorting
{
public static void main(String args[]){
int nums[]={3,4,-1,1};
System.out.println(firstMissingPositive(nums));
}
static int firstMissingPositive(int[] nums) {
//sort the array so the smaller numbers come first
// our ans lies in the range 1....n+1
// we start guessing our smallest missing as 1
// we check if 1 is present if present then we made a wrong guess and
// our next probable ans is smallestMissing++ i.e 2 and so on
// if we ever encounter a number > smallest missing
// we made a correct guess and we break from the loop and return the smallest missing
// note : we don't care for 0s and negatives
Arrays.sort(nums);
int smallestMissing=1; //probable ans
for(int i=0;i<nums.length;i++){
int curr=nums[i];
if(curr==smallestMissing) smallestMissing++;
else if(curr>smallestMissing)
break;
}
return smallestMissing;
}
}
APPROACH 2: USING A HASHSET
TIME COMPLEXITY : O(N)
SPACE COMPLEXITY : O(N)
import java.io.*;
import java.util.*;
class FirstMissingPositive_usingHashing
{
public static void main(String args[]){
int nums[]={3,4,-1,1};
System.out.println(firstMissingPositive(nums));
}
static int firstMissingPositive(int[] nums) {
// our probable ans lies from 1....n+1
// we add all the numbers in nums to an hashset ignoring the negatives and 0s
//then we loop through our range of probable ans i.e 1 to n+1
//the moment we find the first number in our ans range that is not present in the set
// we return it
int n=nums.length;
HashSet<Integer> set= new HashSet<>();
for(int ele : nums){
if(ele>=0)
set.add(ele);
}
for(int i=1;i<=n+1;i++){
if(!set.contains(i))
return i;
}
return -1;
}
}
APPROACH 3: MARKING THE ARRAY
TIME COMPLEXITY : O(N+N+N) = O(3N) = O(N)
SPACE COMPLEXITY : O(1)
import java.io.*;
import java.util.*;
class FirstMissingPositive_Optimal
{
public static void main(String args[]){
int[] nums = {3,4,-1,1};
System.out.println(firstMissingPositive(nums));
}
static int firstMissingPositive(int[] nums) {
// our ans lies within the range 1 to n+1
//step 1 : filter out all those that cannot be our ans
//traverse the array and remove all numbers that are <=0 or >n and mark them with n+1
// if all numbers become >n then we simply return 1
int n=nums.length;
for(int i=0;i<n;i++){
if(nums[i]<=0||nums[i]>n)
nums[i]=n+1;
}
//now all elements in the array are positive and in the range 1 to n+1 i.e our ans range
//we will use the array itself as a hashset and we will mark the array in such a way
//if a element is present in that array we can tell that in O(1)
//how to mark the array ?
//suppose element 3 is present in the array
//so we go to index 3 and convert the number in that index to negative
//i.e if nums[i]=3 then nums[3]= -nums[3]
//but there is a problem if nums[i]=n then nums[n] will be out of bounds since index of last element is n-1
//hence we shift our indexes such that if 1 is present in the array then we mark nums[0] as negative
// similarly if 2 is present then we mark nums[1] as negative and so on
//therefore if x is present in the array we mark[x-1] negative
// so now if n is present in the array then we will mark nums[n-1] neagtive and it will be not out of bounds
//important note : we ignore if nums[x] is n+1
for(int i=0;i<n;i++){
int curr=Math.abs(nums[i]); // we take absolute value since the number in nums[i] might have been turned -ve to mark some element previously
if(curr>n) continue;
if(nums[curr-1]>0) // if duplicates are present then it might have been already marked so we dont mark again
nums[curr-1]=-nums[curr-1];
}
//now we find the first cell which is not negative
// if suppose nums[3] is positive then it means 4 is missing from the array
//cause if 4 were present then nums[3] would have been marked negative
for(int i=0;i<n;i++){
if (nums[i]>0)
return i+1;
}
// if all numbers are negative then it means
// the arrays originally consisted of [1,2,3....n]
//in that case our first missing positive would be n+1
return n+1;
}
}