Count of permutations of an Array having maximum MEXs sum of prefix arrays

• Last Updated : 08 Dec, 2021

Given an array arr of size N, the task is to find the number of its permutations such that the sum of MEXs of its prefix arrays is maximum.

Note: MEX of a set of integers is defined as the smallest non-negative integer that does not belong to this set.

Example:

Input: arr[] = {1, 0, 1}
Output: 2
Explanation:
All permutations and their MEXs are as follows:
[0, 1, 2]  => array : {1, 0, 1}, MEX({1}) + MEX({1, 0}) + MEX({1, 0, 1}) = 0 + 2 + 2 = 4
[0, 2, 1]  => array : {1, 1, 0}, MEX({1}) + MEX({1, 1}) + MEX({1, 1, 0}) = 0 + 0 + 2 = 2
[1, 0, 2]  => array : {0, 1, 1}, MEX({0}) + MEX({0, 1}) + MEX({0, 1, 1}) = 1 + 2 + 2 = 5
[1, 2, 0]  => array : {0, 1, 1}, MEX({0}) + MEX({0, 1}) + MEX({0, 1, 1}) = 1 + 2 + 2 = 5
[2, 0, 1]  => array : {1, 1, 0}, MEX({1}) + MEX({1, 1}) + MEX({1, 1, 0}) = 0 + 0 + 2 = 2
[2, 1, 0]  => array : {1, 0, 1}, MEX({1}) + MEX({1, 0}) + MEX({1, 0, 1}) = 0 + 2 + 2 = 4
Hence the maximum sum is 5 and the number of permutations with this sum are 2.

Input: arr[] = {0, 1, 2, 2, 5, 6}
Output: 12

Approach:

The optimal idea is based on the observation that the sum of MEX of prefix arrays will be maximum when all the distinct elements are arranged in increasing order and the duplicates are present at the end of the array (like 0, 1, 2, 3, …). Once this continuity breaks, the MEX of the rest, after that point remains the same. For example in {0, 1, 2, 2, 5, 6} the MEXs of prefix arrays are {1, 2, 3, 3, 3, 3} in which the continuity breaks at index 3.

Now, to find the count of all permutations with maximum MEXs sum, store the frequency of elements in a map. In a maximum MEX prefix array, the first position is always be filled by 0, and then second by 1, then third by 2 and so on. So try to fill these with the number of choices available and once the point where the continuity breaks is reached, the MEX of all permutations after that point is the same and the elements after this can be arranged in any possible permutation. Now to understand it better, let’s say that there are 0 to Y numbers present in the array then continuity breaks and after that K more elements are present. Then the count of permutations with maximum MEXs sum is:

ans = frequency * frequency * frequency * … * frequency[Y] * factorial[K]

Now, in the case of {0, 1, 2, 2, 5, 6}, the array having the maximum sum of MEXs of its prefix arrays can:

• Only contain 0 at index 0, so the number of choices for the first index is 1.
• Only contain 1 at index 1, so the number of choices here is 1.
• Contain any of the two 2’s present, so the number of choices here is 2.
• Now after this the continuity breaks and the elements after this can be arranged in any order:
• So, the total number of choices after this point is , i.e. .
• Now, the final number of all permutations is .

Follow the steps below to solve the problem:

1. Declare a map mp to store the frequency of the elements.
2. Now create a variable cnt to keep track of the elements present to the right of an element and initialise it with N i.e. total number of elements present.
3. Also declare a variable ans to store the answer and initialize it with 1.
4. Now start iterating from 0 up to the size of the given array i.e. from i = 0 to i < n :
• If mp[i] != 0, this means the continuity prevails till this point and all possible choices (i.e. mp[i]) is to be considered. So, ans will become ans=ans*mp[i] and reduce cnt by 1 to get the elements present to the right of the next element.
• If mp[i] == 0, this means that here the continuity breaks and elements after this can be arranged in any possible permutation. So, breaks the loop here and considered all the permutations possible for the elements present to the right of this point, i.e. factorial of cnt.
5. Print the answer according to the above observation.

Below is the implementation of the above approach:

C++

 // C++ program for the above approach#include  using namespace std; // To calculate the factorialint factorial(int n){    int res = 1, i;    for (i = 2; i <= n; i++) {        res *= i;    }    return res;} // To return the number of permutations of// an array with maximum MEXs sum of prefix arrayint countPermutations(int ar[], int n){     // Map to store the frequency of each element    unordered_map mp;     int ans = 1, cnt = n;     for (int i = 0; i < n; i++) {        mp[ar[i]]++;    }     // Running a loop from i=0 to i

Java

 // java program for the above approachimport java.util.*;class GFG{ // To calculate the factorialstatic int factorial(int n){    int res = 1, i;    for (i = 2; i <= n; i++) {        res *= i;    }    return res;} // To return the number of permutations of// an array with maximum MEXs sum of prefix arraystatic int countPermutations(int[] ar, int n){     // Map to store the frequency of each element    Map mp= new HashMap();    int ans = 1, cnt = n, i;     for (i = 0; i < n; i++) {        if (mp.containsKey(ar[i]))        {            mp.put(ar[i],mp.get(ar[i])+1);        }        else        {            mp.put(ar[i], 1);        }    }     // Running a loop from i=0 to i

Python3

 # Python Program to implement# the above approach # To calculate the factorialdef factorial(n):    res = 1    for i in range(2, n + 1):        res *= i    return res # To return the number of permutations of# an array with maximum MEXs sum of prefix arraydef countPermutations(ar, n):     # Map to store the frequency of each element    mp = dict()     ans = 1    cnt = n     for i in range(n):         if (ar[i] in mp):            mp[ar[i]] += 1        else:            mp[ar[i]] = 1     # Running a loop from i=0 to i

C#

 // C# program for the above approachusing System;using System.Collections.Generic; public class GFG{ // To calculate the factorialstatic int factorial(int n){    int res = 1, i;    for (i = 2; i <= n; i++) {        res *= i;    }    return res;} // To return the number of permutations of// an array with maximum MEXs sum of prefix arraystatic int countPermutations(int[] ar, int n){     // Map to store the frequency of each element    Dictionary mp = new Dictionary();     int ans = 1, cnt = n, i;     for (i = 0; i < n; i++) {        if (mp.ContainsKey(ar[i]))        {            mp[ar[i]] = mp[ar[i]] + 1;        }        else        {            mp.Add(ar[i], 1);        }    }     // Running a loop from i=0 to i

Javascript


Output
2

Time Complexity: O(N)
Auxiliary Space: O(1)

My Personal Notes arrow_drop_up