Given array A[] of size N and integer M, ith element from N elements represents A[i]th type. Create M sets each of size X and consists of the same type of elements. Task for this problem is to maximize value of X.
Constraints:
- 1 <= N <= 105
- 1 <= A[i] <= 109
- 1 <= M <= 109
Examples:
Input: A[] = {1, 5, 2, 1, 1, 1, 2, 5, 7, 2}, M = 4
Output: 2
Explanation: M = 4 sets are created and each set has assigned X = 2 elements.
- first set will be {1, 1} (here first and fourth element are assigned)
- second set will be {1, 1} (here fifth and sixth element are assigned)
- third set will be {2, 2} (here third and seventh element are assigned)
- fourth set will be {5, 5} (here second and eighth element are assigned)
so X = 2 is the answer.
Input: A[] = {5, 4, 3, 2, 1}, M = 2
Output: 1Explanation: M = 2 sets are created and each set has assigned X = 1 element
- first set will be {5} (here first element is assigned)
- second set will be {4} (here second element is assigned)
so X = 1 is the answer
Approach: To solve the problem follow the below idea:
Binary Search can be used to solve this problem and the range of binary search will be 1 to 1e9. f(n) is monotonic function that represents whether M sets of size n can be formed or not. it is of the form TTTTTFFFFFF. we have to find when the last time function was true using Binary Search.
Below are the steps for the above approach:
- Declare HashMap[] that stores frequency of each element of array A[].
- Iterate over all elements in array A[] and fill the HashMap[].
- Set low and high range of binary search.
- ispos(mid) function used to check if M sets each of size mid can formed or not.
- Run while loop till high and low are not equal.
- In while loop find middle element and store it in mid variable.
- Check if M sets each of size mid can be formed or not using ispos() function. If it is true then set low = mid else high = mid – 1.
- After loop ends if ispos() true for high then return high else check if it is true for low then return low else return -1.
Below is the implementation of the above approach:
// C++ code to implement the approach #include <bits/stdc++.h> using namespace std;
// Function to check if array can be distributed in M sets // with each set has mid elements bool ispos( int mid, unordered_map< int , int >& HashMap, int M)
{ // number of sets possible
int numberOfSetsPosofSizeMid = 0;
// iterating in hashmap
for ( auto & e : HashMap) {
// e.second is frequency of one of numbers in array
// it can be divided in e.second / mid sets
numberOfSetsPosofSizeMid += (e.second / mid);
}
// if number of sets of size mid are more
// than required number of distributions than
// return true else return false
return numberOfSetsPosofSizeMid >= M;
} // Function to find Maximize the equal number of // elements distributed in M sets of same type int findMinOp( int A[], int N, int M)
{ // declaring frequencey HashMap
unordered_map< int , int > HashMap;
// iterating over all N elements and filling
// the hashmap
for ( int i = 0; i < N; i++) {
HashMap[A[i]]++;
}
// Range of binary search
int low = 1, high = 1e9;
// Running loop till high
// is not equal to low
while (high - low > 1) {
// mid is average of low and high
int mid = (low + high) / 2;
// Checking test function
if (ispos(mid, HashMap, M)) {
low = mid;
}
else {
high = mid - 1;
}
}
// Checking whether high can be answer
if (ispos(high, HashMap, M))
return high;
// If not then it is low
else if (ispos(low, HashMap, M))
return low;
else
return -1;
} // Driver Code int32_t main() { // Input 1
int N = 10, M = 4;
int A[] = { 1, 5, 2, 1, 1, 1, 2, 5, 7, 2 };
// Function Call
cout << findMinOp(A, N, M) << endl;
// Input 2
int N1 = 5, M1 = 2;
int A1[] = { 5, 4, 3, 2, 1 };
// Function Call
cout << findMinOp(A1, N1, M1) << endl;
return 0;
} |
import java.util.HashMap;
import java.util.Map;
public class Main {
// Function to check if array can be distributed in M
// sets with each set having mid elements
static boolean
isPos( int mid, Map<Integer, Integer> hashMap, int M)
{
// Number of sets possible
int numberOfSetsPosOfSizeMid = 0 ;
// Iterating in HashMap
for (Map.Entry<Integer, Integer> entry :
hashMap.entrySet()) {
// entry.getValue() is the frequency of one of
// the numbers in the array It can be divided
// into entry.getValue() / mid sets
numberOfSetsPosOfSizeMid
+= (entry.getValue() / mid);
}
// If the number of sets of size mid is greater than
// or equal to the required number of distributions
// Return true, else return false
return numberOfSetsPosOfSizeMid >= M;
}
// Function to find maximize the equal number of
// elements distributed in M sets of the same type
static int findMinOp( int [] A, int N, int M)
{
// Declaring frequency HashMap
Map<Integer, Integer> hashMap = new HashMap<>();
// Iterating over all N elements and filling the
// HashMap
for ( int i = 0 ; i < N; i++) {
hashMap.put(A[i],
hashMap.getOrDefault(A[i], 0 ) + 1 );
}
// Range of binary search
int low = 1 , high = ( int )1e9;
// Running loop until high is not equal to low
while (high - low > 1 ) {
// mid is the average of low and high
int mid = (low + high) / 2 ;
// Checking test function
if (isPos(mid, hashMap, M)) {
low = mid;
}
else {
high = mid - 1 ;
}
}
// Checking whether high can be the answer
if (isPos(high, hashMap, M))
return high;
// If not, then it is low
else if (isPos(low, hashMap, M))
return low;
else
return - 1 ;
}
// Driver Code
public static void main(String[] args)
{
// Input 1
int N = 10 , M = 4 ;
int [] A = { 1 , 5 , 2 , 1 , 1 , 1 , 2 , 5 , 7 , 2 };
// Function Call
System.out.println(findMinOp(A, N, M));
// Input 2
int N1 = 5 , M1 = 2 ;
int [] A1 = { 5 , 4 , 3 , 2 , 1 };
// Function Call
System.out.println(findMinOp(A1, N1, M1));
}
} |
def is_pos(mid, hash_map, M):
# Number of sets possible
number_of_sets_pos_of_size_mid = 0
# Iterating in hash_map
for key, value in hash_map.items():
# value is the frequency of one of the numbers in array
# it can be divided into value // mid sets
number_of_sets_pos_of_size_mid + = value / / mid
# If the number of sets of size mid is more than the required number of distributions
# then return True, else return False
return number_of_sets_pos_of_size_mid > = M
def find_min_op(arr, N, M):
# Declaring frequency hash_map
hash_map = {}
# Iterating over all N elements and filling the hash_map
for num in arr:
if num in hash_map:
hash_map[num] + = 1
else :
hash_map[num] = 1
# Range of binary search
low, high = 1 , 10 * * 9
# Running loop until high is not equal to low
while high - low > 1 :
# mid is the average of low and high
mid = (low + high) / / 2
# Checking the test function
if is_pos(mid, hash_map, M):
low = mid
else :
high = mid - 1
# Checking whether high can be the answer
if is_pos(high, hash_map, M):
return high
# If not, then it is low
elif is_pos(low, hash_map, M):
return low
else :
return - 1
# Driver Code if __name__ = = "__main__" :
# Input 1
N = 10
M = 4
A = [ 1 , 5 , 2 , 1 , 1 , 1 , 2 , 5 , 7 , 2 ]
# Function Call
print (find_min_op(A, N, M))
# Input 2
N1 = 5
M1 = 2
A1 = [ 5 , 4 , 3 , 2 , 1 ]
# Function Call
print (find_min_op(A1, N1, M1))
|
// C# code to implement the approach using System;
using System.Collections.Generic;
class GFG {
// Function to check if array can be distributed in M sets
// with each set having mid elements
static bool IsPos( int mid, Dictionary< int , int > HashMap, int M) {
// number of sets possible
int numberOfSetsPosOfSizeMid = 0;
// iterating in hashmap
foreach ( var e in HashMap) {
// e.Value is frequency of one of numbers in array
// it can be divided in e.Value / mid sets
numberOfSetsPosOfSizeMid += (e.Value / mid);
}
// if number of sets of size mid are more
// than required number of distributions, return true, else return false
return numberOfSetsPosOfSizeMid >= M;
}
// Function to find Maximize the equal number of
// elements distributed in M sets of the same type
static int FindMinOp( int [] A, int N, int M) {
// declaring frequency HashMap
Dictionary< int , int > HashMap = new Dictionary< int , int >();
// iterating over all N elements and filling the hashmap
for ( int i = 0; i < N; i++) {
if (HashMap.ContainsKey(A[i])) {
HashMap[A[i]]++;
} else {
HashMap.Add(A[i], 1);
}
}
// Range of binary search
int low = 1, high = ( int )1e9;
// Running loop till high
// is not equal to low
while (high - low > 1) {
// mid is the average of low and high
int mid = (low + high) / 2;
// Checking test function
if (IsPos(mid, HashMap, M)) {
low = mid;
} else {
high = mid - 1;
}
}
// Checking whether high can be the answer
if (IsPos(high, HashMap, M)) {
return high;
}
// If not then it is low
else if (IsPos(low, HashMap, M)) {
return low;
} else {
return -1;
}
}
// Driver Code
public static void Main ( string [] args) {
// Input 1
int [] A = { 1, 5, 2, 1, 1, 1, 2, 5, 7, 2 };
int N = 10, M = 4;
// Function Call
Console.WriteLine(FindMinOp(A, N, M));
// Input 2
int [] A1 = { 5, 4, 3, 2, 1 };
int N1 = 5, M1 = 2;
// Function Call
Console.WriteLine(FindMinOp(A1, N1, M1));
}
} |
// JavaScript Implementation // Function to check if array can be distributed in M sets // with each set has mid elements function ispos(mid, HashMap, M) {
// number of sets possible
let numberOfSetsPosofSizeMid = 0;
// iterating in hashmap
for (let key in HashMap) {
// e.second is frequency of one of numbers in array
// it can be divided in e.second / mid sets
numberOfSetsPosofSizeMid += Math.floor(HashMap[key] / mid);
}
// if number of sets of size mid are more
// than required number of distributions than
// return true else return false
return numberOfSetsPosofSizeMid >= M;
} // Function to find Maximize the equal number of // elements distributed in M sets of same type function findMinOp(A, N, M) {
// declaring frequencey HashMap
let HashMap = {};
// iterating over all N elements and filling
// the hashmap
for (let i = 0; i < N; i++) {
if (HashMap[A[i]]) {
HashMap[A[i]]++;
} else {
HashMap[A[i]] = 1;
}
}
// Range of binary search
let low = 1, high = 1e9;
// Running loop till high
// is not equal to low
while (high - low > 1) {
// mid is average of low and high
let mid = Math.floor((low + high) / 2);
// Checking test function
if (ispos(mid, HashMap, M)) {
low = mid;
} else {
high = mid - 1;
}
}
// Checking whether high can be answer
if (ispos(high, HashMap, M)) {
return high;
}
// If not then it is low
else if (ispos(low, HashMap, M)) {
return low;
} else {
return -1;
}
} // Driver Code let N = 10, M = 4; let A = [1, 5, 2, 1, 1, 1, 2, 5, 7, 2]; // Function Call console.log(findMinOp(A, N, M)); let N1 = 5, M1 = 2; let A1 = [5, 4, 3, 2, 1]; // Function Call console.log(findMinOp(A1, N1, M1)); // This code is contributed by Sakshi |
2 1
Time Complexity: O(NlogN)
Auxiliary Space: O(1)