Open In App

Minimum operations for which all integers from [0, N] appears as smallest positive missing number (MEX)

Improve
Improve
Like Article
Like
Save
Share
Report

Given an array arr[], of size N the task is to find the minimum operations on the array such that in each operation any element in the array can be chosen and incremented by 1 so that the MEX is i for all i in the range [0, n]. If for any i if the MEX is not i print -1.

Examples : 

Input : arr[] = {3, 0, 1, 0, 3}
Output: 
MEX for i = 0 is 2
MEX for i = 1 is 1
MEX for i = 2 is 0
MEX for i = 3 is 4
MEX for i = 4 is 2
MEX for i = 5 is 3
Explanation: 
For MEX = 0 
In operation 1 choose index 1 and increment it by 1 
In operation 2 choose index 3 and increment it by 1 the array becomes {3, 1, 1, 1, 3} MEX = 0. So 2 operations.
For MEX =1
In operation 1 choose index 2 and increment  it by 1 the array becomes {3, 0, 2, 0, 3} MEX = 1. So 1 operation.
For MEX = 2, So 0 operation.
It is already having MEX = 2 
For MEX = 3
In operation 1 choose index 0 and increment it by 1 
In operation 2 choose index 3 and increment it by 1
In operation 3 choose index 1 and increment it by 1  
In operation 3 choose index 1 and increment it by 1  , the array becomes {4, 2, 1, 0, 4} MEX = 3 so 4 operations.
Same for MEX = 4, 5 .

Input : {1, 2, 3, 4}
Output: 0 -1, -1, -1, -1
MEX for i = 0 is 0
MEX for i = 1 is -1
MEX for i = 2 is -1
MEX for i = 3 is -1
MEX for i = 4 is -1

Approach: Hashing can be used to solve this problem to store the frequencies of the element and the stack can be used to store the repeated elements in the array. Hashmap can be used to store the frequencies for a MEX = i if i already exists in the hashmap increment all that occurrences and store the repeated elements in the stack else if the frequency of i is 0 it is already a MEX so 0 operations, Now look for the repeating occurrences in the stack and make it to current i so that for i+1, i would not become MEX. Follow these steps to solve this problem:

  • Initialize an unordered_map freq[] to store the frequencies of the array arr[] and a variable is_possible to keep track of the possibility of MEX.
  • Iterate through the array arr[] and store the frequencies in the hashmap freq.
  • Initialize the stack stk[] and the vector ops,  to store the minimum operations for MEX = i, prev_cost to store the cost required to increment the repeated element.
  • If is_possible == 0, MEX = i is not possible so store -1.
  • Else store freq[i]+ prev_cost in the ops.
    • If freq[i] is equal to 0 Check if there is some element in the stack pop it and increment it to i and increment prev_cost to i-j and increment freq[i], if the stack is empty make is_possible to false.
    • Else if the freq[i]>1 push the repeated into the stack stk[] and decrement freq[i].
  • Now print the vector ops which contains the minimum operations to make the MEX = i [0, n].

Below is the implementation of the above approach.

C++

// C++ program for the above approach
#include <bits/stdc++.h>
using namespace std;

// Function to find the minimum operations
// to make the MEX = i
void find_min_operations(int arr[], int n)
{

    // Initialize an unordered_map
    // to store the frequencies
    unordered_map<int, int> freq;

    // is_possible to store
    // the possibility of MEX = i
    bool is_possible = true;

    // count the frequencies
    // and store into the freq
    for (int i = 0; i < n; i++) {
        freq[arr[i]]++;
    }

    // Initialize stack to store
    // the repeated elements
    stack<int> stk;

    // ops store the minimum
    // operations required for MEX =i
    vector<int> ops;

    // prev_cost to store the
    // cost to increment some
    // repeated element to i-1
    // if MEX initially is i-1 so
    // that  MEX remains i
    int prev_cost = 0;
    for (int i = 0; i <= n; i++) {

        // Push -1 if it is not possible
        if (is_possible == 0)
            ops.push_back(-1);
        else {

            ops.push_back(freq[i] + prev_cost);

            // If frequency of the element is 0
            // then check for repeated element
            // in the stack so that it can be added
            // with i-j operations in next iteration
            // and can be made it to i.
            if (freq[i] == 0) {

                // Check for repeated
                // element in the stack
                if (!stk.empty()) {
                    int j = stk.top();
                    stk.pop();
                    prev_cost += i - j;
                    // Increment the frequency of i since
                    // the repeated element j is made to i

                    freq[i]++;
                }

                // If no repeated element
                // no possibility for MEX = i+1
                // so make is_possible=false
                else
                    is_possible = false;
            }

            // If i is already available
            else {

                // Push the repeated elements
                // into the stack
                while (freq[i] > 1) {
                    stk.push(i);
                    freq[i]--;
                }
            }
        }
    }

    for (int i = 0; i < ops.size(); i++) {
        cout << "MEX for i = "
             << i << " is " << ops[i]
             << endl;
    }
}

// Driver Code
int main()
{

    // Initializing array arr[]
    int arr[] = { 3, 0, 1, 0, 3 };
    int n = sizeof(arr) / sizeof(arr[0]);

    // Function call
    find_min_operations(arr, n);
    return 0;
}

Java

// Java program for the above approach

import java.util.ArrayList;
import java.util.Stack;
import java.util.HashMap;

class GFG {

  // Function to find the minimum operations
  // to make the MEX = i
  static void find_min_operations(int arr[], int n) {

    // Initialize an unordered_map
    // to store the frequencies
    HashMap<Integer, Integer> freq = new HashMap<Integer, Integer>();

    // is_possible to store
    // the possibility of MEX = i
    boolean is_possible = true;

    // count the frequencies
    // and store into the freq
    for (int i = 0; i < n; i++) {
      freq.put(arr[i], freq.getOrDefault(arr[i], 0) + 1);
    }

    // Initialize stack to store
    // the repeated elements
    Stack<Integer> stk = new Stack<Integer>();

    // ops store the minimum
    // operations required for MEX =i
    ArrayList<Integer> ops = new ArrayList<Integer>();

    // prev_cost to store the
    // cost to increment some
    // repeated element to i-1
    // if MEX initially is i-1 so
    // that MEX remains i
    int prev_cost = 0;
    for (int i = 0; i <= n; i++) {

      // Push -1 if it is not possible
      if (is_possible == false)
        ops.add(-1);
      else {

        if(freq.containsKey(i)){

        ops.add(freq.get(i) + prev_cost);
        }else{
          ops.add(prev_cost);
        }

        // If frequency of the element is 0
        // then check for repeated element
        // in the stack so that it can be added
        // with i-j operations in next iteration
        // and can be made it to i.
        if (freq.containsKey(i) == false) {

          // Check for repeated
          // element in the stack
          if (!stk.empty()) {
            int j = stk.peek();
            stk.pop();
            prev_cost += i - j;
            // Increment the frequency of i since
            // the repeated element j is made to i
            freq.put(freq.getOrDefault(i, 0), 1);
          }

          // If no repeated element
          // no possibility for MEX = i+1
          // so make is_possible=false
          else
            is_possible = false;
        }

        // If i is already available
        else {

          // Push the repeated elements
          // into the stack
          while (freq.get(i) > 1) {
            stk.push(i);
            freq.put(i, freq.get(i) - 1);
          }
        }
      }
    }

    for (int i = 0; i < ops.size(); i++) {
      System.out.println("MEX for i = " + i + " is " + ops.get(i));
    }
  }

  // Driver Code
  public static void main(String args[]) {

    // Initializing array arr[]
    int arr[] = { 3, 0, 1, 0, 3 };
    int n = arr.length;

    // Function call
    find_min_operations(arr, n);
  }
}

Python3

# Python3 program for the above approach
from collections import deque

# Function to find the minimum operations
# to make the MEX = i
def find_min_operations(arr, n):
    
    # Initialize an unordered_map
    # to store the frequencies
    freq = {}

    # is_possible to store
    # the possibility of MEX = i
    is_possible = True

    # Count the frequencies
    # and store into the freq
    for i in range(0, n):
        if arr[i] in freq:
            freq[arr[i]] += 1
        else:
            freq[arr[i]] = 1

    # Initialize stack to store
    # the repeated elements
    stk = deque()

    # ops store the minimum
    # operations required for MEX =i
    ops = []

    # prev_cost to store the
    # cost to increment some
    # repeated element to i-1
    # if MEX initially is i-1 so
    # that MEX remains i
    prev_cost = 0
    for i in range(0, n + 1):

        # Push -1 if it is not possible
        if (is_possible == 0):
            ops.append(-1)
        else:
            if i in freq:
                ops.append(freq[i] + prev_cost)
            else:
                ops.append(prev_cost)

            # If frequency of the element is 0
            # then check for repeated element
            # in the stack so that it can be added
            # with i-j operations in next iteration
            # and can be made it to i.
            if (not (i in freq)):

                # Check for repeated
                # element in the stack
                if (len(stk) != 0):
                    j = stk.popleft()
                    prev_cost += i - j
                    
                    # Increment the frequency of i since
                    # the repeated element j is made to i
                    freq[i] = freq[i] + 1 if i in freq else 1

                # If no repeated element
                # no possibility for MEX = i+1
                # so make is_possible=false
                else:
                    is_possible = False

            # If i is already available
            else:

                # Push the repeated elements
                # into the stack
                while (freq[i] > 1):
                    stk.append(i)
                    freq[i] -= 1

    for i in range(0, len(ops)):
        print(f"MEX for i = {i} is {ops[i]}")

# Driver Code
if __name__ == "__main__":

    # Initializing array arr[]
    arr = [ 3, 0, 1, 0, 3 ]
    n = len(arr)

    # Function call
    find_min_operations(arr, n)

# This code is contributed by rakeshsahni

C#

// C# program for the above approach
using System;
using System.Collections;
using System.Collections.Generic;

public class GFG {

  // Function to find the minimum operations
  // to make the MEX = i
  static void find_min_operations(int[] arr, int n)
  {
    
    // Initialize an unordered_map
    // to store the frequencies
    Dictionary<int, int> freq
      = new Dictionary<int, int>();

    // is_possible to store
    // the possibility of MEX = i
    bool is_possible = true;

    // count the frequencies
    // and store into the freq
    for (int i = 0; i < n; i++) {
      if (freq.ContainsKey(arr[i])) {
        freq[arr[i]] += 1;
      }
      else {
        freq[arr[i]] = 1;
      }
    }

    // Initialize stack to store
    // the repeated elements
    Stack stk = new Stack();

    // ops store the minimum
    // operations required for MEX =i
    ArrayList ops = new ArrayList();

    // prev_cost to store the
    // cost to increment some
    // repeated element to i-1
    // if MEX initially is i-1 so
    // that MEX remains i
    int prev_cost = 0;
    for (int i = 0; i <= n; i++) {
      // Push -1 if it is not possible
      if (is_possible == false)
        ops.Add(-1);
      else {
        if (freq.ContainsKey(i)) {
          ops.Add(freq[i] + prev_cost);
        }
        else {
          ops.Add(prev_cost);
        }

        // If frequency of the element is 0
        // then check for repeated element
        // in the stack so that it can be added
        // with i-j operations in next iteration
        // and can be made it to i.
        if (freq.ContainsKey(i) == false) {

          // Check for repeated
          // element in the stack
          if (stk.Count != 0) {
            int j = (int)stk.Peek();
            stk.Pop();
            prev_cost += i - j;
            // Increment the frequency of i
            // since the repeated element j is
            // made to i
            if (freq.ContainsKey(i)) {
              freq[i] += 1;
            }
            else {
              freq[i] = 1;
            }
          }

          // If no repeated element
          // no possibility for MEX = i+1
          // so make is_possible=false
          else
            is_possible = false;
        }

        // If i is already available
        else {

          // Push the repeated elements
          // into the stack
          while (freq[i] > 1) {
            stk.Push(i);
            freq[i] -= 1;
          }
        }
      }
    }

    for (int i = 0; i < ops.Count; i++) {
      Console.WriteLine("MEX for i = " + i + " is "
                        + ops[i]);
    }
  }

  static public void Main()
  {

    // Initializing array arr[]
    int[] arr = { 3, 0, 1, 0, 3 };
    int n = arr.Length;

    // Function call
    find_min_operations(arr, n);
  }
}

// This code is contributed by lokeshmvs21.

Javascript

// JS program for the above approach

// Function to find the minimum operations
// to make the MEX = i
function find_min_operations(arr, n)
{

    // Initialize an unordered_map
    // to store the frequencies
    let freq = new Map([]);

    // is_possible to store
    // the possibility of MEX = i
    let is_possible = true;

    for(let i=0;i<100;i++)
    {
        freq.set(i,0);
    }

    // count the frequencies
    // and store into the freq
    for (let i = 0; i < n; i++) {
        freq.set(arr[i],freq.get(arr[i])+1);
    }

    // Initialize stack to store
    // the repeated elements
    let stk  = [];

    // ops store the minimum
    // operations required for MEX =i
    let ops = [];

    // prev_cost to store the
    // cost to increment some
    // repeated element to i-1
    // if MEX initially is i-1 so
    // that  MEX remains i
    let prev_cost = 0;
    for (let i = 0; i <= n; i++) {

        // Push -1 if it is not possible
        if (is_possible == 0)
            ops.push(-1);
        else {

            ops.push(freq.get(i) + prev_cost);

            // If frequency of the element is 0
            // then check for repeated element
            // in the stack so that it can be added
            // with i-j operations in next iteration
            // and can be made it to i.
            if (freq.get(i) == 0) {

                // Check for repeated
                // element in the stack
                if (stk.length>0) {
                    let j = stk[stk.length-1];
                    stk.pop();
                    prev_cost += i - j;
                    // Increment the frequency of i since
                    // the repeated element j is made to i

                    freq.set(i,freq.get(i)+1);
                }

                // If no repeated element
                // no possibility for MEX = i+1
                // so make is_possible=false
                else
                    is_possible = false;
            }

            // If i is already available
            else {

                // Push the repeated elements
                // into the stack
                while (freq.get(i) > 1) {
                    stk.push(i);
                    freq.set(i,freq.get(i)-1);
                }
            }
        }
    }

    for (let i = 0; i < ops.length; i++) {
        console.log("MEX for i = ", i , " is " , ops[i]);
    }
}
// Initializing array arr[]
let arr = [ 3, 0, 1, 0, 3 ];
let n = arr.length;

// Function call
find_min_operations(arr, n);

// This code is contributed by akashish__
Output

MEX for i = 0 is 2
MEX for i = 1 is 1
MEX for i = 2 is 0
MEX for i = 3 is 4
MEX for i = 4 is 2
MEX for i = 5 is 3

Time Complexity: O(N)  where N is the size of the array
Auxiliary Space: O(N)



Last Updated : 23 Nov, 2022
Like Article
Save Article
Previous
Next
Share your thoughts in the comments
Similar Reads