Minimum operations for which all integers from [0, N] appears as smallest positive missing number (MEX)
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__ |
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)
Please Login to comment...