Solution: First Missing Positive

Let's solve the First Missing Positive problem using the Cyclic sort pattern.

Statement#

Given an unsorted integer array, nums, return the smallest missing positive integer. Create an algorithm that runs with an O(n)O(n) time complexity and utilizes a constant amount of space.

Note: The smallest missing positive isn’t the first positive number that’s missing in the range of elements in the input, but the first positive number that’s missing if we start from 11.

Constraints:

  • 11 \leq nums.length 103\leq 10^3

  • 231-2^{31} \leq nums[i] 2311\leq 2^{31} - 1

Solution#

So far, you have probably brainstormed some approaches and have an idea of how to solve this problem. Let’s explore some of these approaches and figure out which one to follow based on considerations such as time complexity and any implementation constraints.

Naive approach#

  • The brute force approach would be to search for every positive integer in the array, starting from 11 and incrementing the number to be searched until we find the first missing positive number. It will result in an algorithm with the time complexity of O(n2)O(n^2).

  • A solution that everyone thinks about is sorting the array and then searching for the smallest positive number. However, this also gives us a time complexity of O(nlogn)O(n \log n)where n is the number of elements present in our array.

  • The final approach we would discuss is storing all the numbers in a hash table and returning the first positive value we don't encounter. This solution would fulfill the time complexity condition of O(n)O(n) but still requires extra space. That's where cyclic sort comes in.

Optimized approach using cyclic sort#

An array of size nn containing numbers ranging from 11 to nn can be sorted using the cyclic sort approach in O(n)O(n). Here, we have two problems. First, the array may have negative numbers as well. Second, the array does not have all consecutive numbers. The first problem can be solved by simply ignoring the negative values. The second problem can be solved by linearly scanning the sorted array in O(n)O(n). So, overall, our problem is solved in O(n)O(n) time and O(1)O(1) space, because cyclic sort sorts the elements in-place with O(1)O(1) extra space. Now, we can proceed further and discuss our algorithm.

The algorithm iterates over each element of the array, and for each element, it determines the correct position where the element should be placed. It does this by subtracting 11 from the element value because of 0-based indexing. It checks the following conditions for each element after determining its correct position:

  • If the current element is in the [1n][1-n] range, and if it is not already at its correct position, swap the current element with the element at its correct position.

  • Otherwise, move on to the next element.

After placing all the elements at the correct positions, traverse the array again and check if the value at each index is equal to its index plus 11. If it is not, return the index plus 11 as the smallest missing positive integer.

If all the values are in order, return the length of the array plus 1 as the smallest missing positive integer.

Let’s look at the following example to understand this in a better way:

Created with Fabric.js 3.6.6 Array 3 4 -1 1 We have an unsorted array, so let'ssort it before finding the missinginteger.

1 of 10

Created with Fabric.js 3.6.6 Array 3 4 -1 1 We have found that 3 is not atits correct position, so we canswap it with the element at itscorrect position.

2 of 10

Created with Fabric.js 3.6.6 Array -1 4 3 1 We have placed 3 at it's correctposition, but we have to checkif the swapped element is indeedat its correct position.

3 of 10

Created with Fabric.js 3.6.6 Array -1 4 3 1 The element was a negativenumber. Hence, we ignore itand check the next element.

4 of 10

Created with Fabric.js 3.6.6 Array -1 4 3 1 The number is not at its correctposition. Hence, we can swap it.

5 of 10

Created with Fabric.js 3.6.6 Array -1 1 3 4 We have placed 4 at it's correctposition, but we have to checkif the swapped element is indeedat its correct position.

6 of 10

Created with Fabric.js 3.6.6 Array -1 1 3 4 The number is not at its correctposition. Hence, we can swap it.

7 of 10

Created with Fabric.js 3.6.6 Array 1 -1 3 4 The new element is a negativenumber. Hence, we can moveforward.

8 of 10

Created with Fabric.js 3.6.6 Array 1 -1 3 4 The next two elements are attheir correct positions. Hence,we can get to the next processof checking the first missingpositive integer.

9 of 10

Created with Fabric.js 3.6.6 Array While traversing, we foundthat 2 wasn't present at the1st index. Hence, we concludedthat it is the missing number. 1 -1 3 4

10 of 10

Let’s look at the implementation of the solution discussed above:

First Missing Positive
Solution summary#
  1. Iterate over all the elements in nums and swap them with their correct position until all elements are in their correct positions.

  2. Iterate over nums again and check if each element is equal to its index plus 1.

  3. If an element is not in the correct position, return the index plus 1, of the element that is out of order, as the smallest missing positive number.

  4. If all elements are in order, return the length of the array plus 1 as the smallest missing positive integer.

Time complexity#

The algorithm traverses over the array two times, and in both traversals, it iterates over each element exactly once. Therefore, the time complexity of this algorithm is O(n)O(n), where nn is the length of the nums.

Space complexity#

The space complexity of the algorithm is O(1)O(1) as it uses only a constant amount of space.

First Missing Positive

Topological Sort: Introduction