Smallest Positive Missing Number (Solution)

Smallest Positive Missing Number

Problem Statement

Given an array containing both positive and negative numbers, find the smallest positive number excluded from the array.

Sample Test Cases

Input 1: a = [2, 3, 7, 6, 8, -1, -10, 15]
Output 1: 1
Explanation 1: 1 is the smallest positive integer missing from the array.

Input 2: a = [2, 3, -7, 6, 8, 1, -10, 15]
Output 2: 4
Explanation 2: 4 is the smallest positive integer missing from the array.

Approach 1: Looping Over Positive Integers

We can solve the problem naively by looping over all the positive integers and checking if each of them is present in the array or not. Whenever a number is not found in the array, we return it and break the algorithm.

C++ Code

int getMEX(vector < int > & a) {
  bool found = false;
  for (int i = 1;; i++) {
    found = false;
    for (auto x: a) {
      if (x == i) {
        found = true;
        break;
      }
    }
    if (!found) {
      return i;
    }
  }
}

Java Code

public static int getMEX(int[] a) {
  boolean found = false;
  for (int i = 1;; i++) {
    found = false;
    for (int j = 0; j < a.length; j++) {
      int x = a[j];
      if (x == i) {
        found = true;
        break;
      }
    }
    if (!found) {
      return i;
    }
  }
}

Python Code

def getMEX(a):
    found = False
    n = len(a)
    for i in range(1, n + 2):
        found = False
        for j in range(n):
            if a[j] == i:
                found = True
                break
        if found == False:
            return i

Complexity Analysis

  • Time Complexity: O(n * n)
  • Space Complexity: O(1)

Approach 2: Hashing Method

We can solve this problem in linear time by using hashing. We loop over all the positive numbers, and check if it is present in the array or not by using a lookup table or hash map in O(1) time. The first element not found in the array will be the answer.

C++ Implementation

int getMEX(vector < int > & a) {
  int n = a.size();
  unordered_set < int > hash(a.begin(), a.end());
  for (int i = 1; i <= n + 1; i++) {
    if (hash.find(i) == hash.end()) {
      return i;
    }
  }
}

Java Implementation

public static int getMEX(int[] a) {
  int n = a.length;
  HashSet < Integer > hash = new HashSet < Integer > ();
  for (int i = 0; i < n; i++) {
    hash.add(a[i]);
  }
  for (int i = 1; i <= n + 1; i++) {
    if (!hash.contains(i)) {
      return i;
    }
  }
  return -1;
}

Python Implementation

def getMEX(a):
    n = len(a)
    b = a
    hash = set(b)
    for i in range(1, n + 2):
        if i not in hash:
            return i

Complexity Analysis

  • Time Complexity: O(n)
  • Space Complexity: O(n)

Approach 3

The algorithm is described as follows:

  • Move all the non-positive numbers to the left side of the array and separate out the positive numbers. After applying this function, all the nonpositive numbers in the array must appear before any positive number in the array.
  • We now start iterating on the array from the index which has the first positive element. For each element ele, to mark that it is present in the array, we change the value at index ele to its negative. Then, we again iterate on the array and return the first index with a positive value.

C++ Implementation

int distribute(int a[], int n) {
  int j = 0;
  for (int i = 0; i < n; i++) {
    if (a[i] <= 0) {
      swap(a[i], a[j]);
      j++;
    }
  }
  return j;
}
int getMEXUtil(int a[], int till) {
  for (int i = 0; i < till; i++) {
    if (abs(a[i]) - 1 < till && a[abs(a[i]) - 1] > 0) {
      a[abs(a[i]) - 1] *= (-1);
    }
  }
  for (int i = 0; i < till; i++) {
    if (a[i] > 0) {
      return i + 1;
    }
  }
  return till + 1;
}
int getMEX(int a[], int n) {
  int moved = distribute(a, n);
  return getMEXUtil(a + moved, n - moved);
}

Java Implementation

public static int distribute(int a[], int n) {
  int j = 0;
  for (int i = 0; i < n; i++) {
    if (a[i] <= 0) {
      int temp = a[i];
      a[i] = a[j];
      a[j] = temp;
      j++;
    }
  }
  return j;
}
public static int getMEXUtil(int a[], int till) {
  for (int i = 0; i < till; i++) {
    if (Math.abs(a[i]) - 1 < till && a[Math.abs(a[i]) - 1] > 0) {
      a[Math.abs(a[i]) - 1] *= (-1);
    }
  }
  for (int i = 0; i < till; i++) {
    if (a[i] > 0) {
      return i + 1;
    }
  }
  return till + 1;
}
public static int getMEX(int a[], int n) {
  int moved = distribute(a, n);
  int[] aCopy = new int[n - moved];
  int j = 0;
  for (int i = moved; i < n; i++) {
    aCopy[j] = a[i];
    j++;
  }
  return getMEXUtil(aCopy, n - moved);
}

Python Implementation

def distribute(a, n):
    j = 0
    for i in range(n):
        if a[i] <= 0:
            temp = a[i]
            a[i] = a[j]
            a[j] = temp
            j += 1
    return j


def getMEXUtil(a, n):
    for i in range(n):
        x = abs(a[i])
        if x - 1 < n and a[x - 1] > 0:
            a[x - 1] *= -1
    for i in range(n):
        if a[i] > 0:
            return i + 1
    return n + 1


def getMEX(a, n):
    moved = distribute(a, n)
    return getMEXUtil(a[moved:], n - moved)

Complexity Analysis

  • Time Complexity: O(n)
  • Space Complexity: O(1)

Approach 4

We can solve this problem by making an auxiliary array of size the same as that of our given array. Now we traverse our original array, and whenever we find a positive value in the array, we update the index equal to that value with 1. Then we make another traversal through the auxiliary array and return the index + 1  of the first 0 encountered.

C++ Code

int getMEX(vector < int > & a, int n) {
  vector < bool > found(n + 2, false);
  for (auto x: a) {
    if (x > 0 && x <= n) {
      found[x] = true;
    }
  }
  for (int i = 1; i <= n + 1; i++) {
    if (!found[i]) {
      return i;
    }
  }
  return n + 1;
}

Java Code

public static int getMEX(int[] a, int n) {
  boolean[] found = new boolean[n + 2];
  for (int x: a) {
    if (x > 0 && x <= n) {
      found[x] = true;
    }
  }
  for (int i = 1; i <= n + 1; i++) {
    if (!found[i]) {
      return i;
    }
  }
  return n + 1;
}

Python Code

def getMEX(a, n):
    found = [False] * (n + 2)
    for i in range(n):
        if a[i] > 0 and a[i] <= n:
            found[a[i]] = True
    for i in range(1, n + 2):
        if found[i] == False:
            return i
    return n + 1

Complexity Analysis

  • Time Complexity: O(n)
  • Space Complexity: O(n)

Approach 5:

The algorithm is described as follows:

  • If 1 is not present in the array, return 1.
  • Traverse the array and change every element less than 1 or greater than n to 1.
  • Traverse the array again and for each element a[i], update it to a[(a[i] – 1) % n] += n.
  • Again traverse the array and return the first index which has a value less than or equal to n. If not found, return n + 1.

C++ Implementation

int getMEX(vector < int > & a, int n) {
  bool ok = false;
  for (int i = 0; i < n; i++) {
    ok |= (a[i] == 1);
  }
  if (!ok) {
    return 1;
  }
  for (auto & x: a) {
    if (x <= 0 || x > n) {
      x = 1;
    }
  }
  for (int i = 0; i < n; i++) {
    a[((a[i] - 1) % n + n) % n] += n;
  }
  int result = n + 1;
  for (int i = 0; i < n; i++) {
    if (a[i] <= n) {
      result = i + 1;
      break;
    }
  }
  return result;
}

Java Implementation

public static int getMEX(int[] a, int n) {
  boolean ok = false;
  for (int i = 0; i < n; i++) {
    ok |= (a[i] == 1);
  }
  if (!ok) {
    return 1;
  }
  for (int i = 0; i < n; i++) {
    if (a[i] <= 0 || a[i] > n) {
      a[i] = 1;
    }
  }
  for (int i = 0; i < n; i++) {
    a[((a[i] - 1) % n + n) % n] += n;
  }
  int result = n + 1;
  for (int i = 0; i < n; i++) {
    if (a[i] <= n) {
      result = i + 1;
      break;
    }
  }
  return result;
}

Python Implementation

def getMEX(a, n):
    if 1 not in a:
        return 1
    for i in range(n):
        if a[i] <= 0 or a[i] > n:
            a[i] = 1
    for i in range(n):
        a[((a[i] - 1) % n + n) % n] += n
    for i in range(n):
        if a[i] <= n:
            return i + 1
    return n + 1

Complexity Analysis:

  • Time Complexity: O(n)
  • Space Complexity: O(1)

Approach 6

The algorithm is described as follows:

  • Traverse the array, and while a[i] > 1 and a[i] <= n and a[i] != a[a[i] – 1], conditions are true, swap a[i] with a[a[i] – 1].
  • Traverse the array again, and return the first index where a[i] != i + 1. If such an index is not found, return n + 1.

C++ Implementation For The Approach

int getMEX(vector < int > & a, int n) {
  for (int i = 0; i < n; i++) {
    while (a[i] > 0 && a[i] <= n && a[i] != a[a[i] - 1]) {
      swap(a[i], a[a[i] - 1]);
    }
  }
  int result = n + 1;
  for (int i = 1; i <= n; i++) {
    if (i != a[i - 1]) {
      result = i;
      break;
    }
  }
  return result;
}

Java Implementation For The Approach

public static int getMEX(int[] a, int n) {
  for (int i = 0; i < n; i++) {
    while (a[i] > 0 && a[i] <= n && (a[i] != a[a[i] - 1])) {
      int temp = a[a[i] - 1];
      a[a[i] - 1] = a[i];
      a[i] = temp;
    }
  }
  int result = n + 1;
  for (int i = 1; i <= n; i++) {
    if (i != a[i - 1]) {
      result = i;
      break;
    }
  }
  return result;
}

Python Implementation For The Approach

def getMEX(a, n):
    for i in range(n):
        while a[i] > 0 and a[i] <= n and a[i] != a[a[i] - 1]:
            temp = a[a[i] - 1]
            a[a[i] - 1] = a[i]
            a[i] = temp
    for i in range(n):
        if a[i] != (i + 1):
            return i + 1
    return n + 1

Complexity Analysis

  • Time Complexity: O(n)
  • Space Complexity: O(1)

FAQs

Q. Can this problem be solved by using sorting?
A. Yes, this problem can be solved using standard sorting algorithms, albeit in O(nlogn).

Q. What is the complexity of the lookup operations of hashmap in approach 2?
A. The lookup time complexity of hashmaps is amortized O(1) with the use of a good hash function.

Previous Post

Largest Subarray of 0’s and 1’s

Next Post

Egg Dropping Puzzle

Exit mobile version