There is a school in a village. It has N classes. One fine day, someone donated B blueberry cheesecakes to schools. Now you need to divide these cakes such that:
- Each class gets at least 1 cake.
- Each class will share the cake(s) among students.
- Your aim is to minimize the maximum number of students per cake in any class.
Examples:
Input: N = 1, B = 2, ClassList = 35
Output: 18
Explanation: The number of students in each cake will be 17 and 18, and the maximum of them is 18.Input: N = 2, B = 7, ClassList = 20 50
Output: 10
Explanation: The number of cakes will be 2 for the first and 5 for the second class, so there will be a maximum of 10 students for each cake.
Source: Directi Interview | Set 8 (Off-Campus)
Basic Approach: The basic way to solve the problem is as follows:
- First, we will check whether is it possible to distribute at least 1 cake per class, distributing will not be possible only when the number of cakes is less than the number of classes, returning -1 in this scenario.
- After that we will distribute 1 cake per class, then we will find the class that has a maximum number of students per cake and give them an extra cake to minimize it, again repeat the same process until we have no cakes left.
- At the end, we will return the maximum number of students per cake among all classes.
Below is the implementation of the above idea.
// C++ code for the above approach: #include <bits/stdc++.h> using namespace std;
int distribution( int n, int b, vector< float >& ClassList)
{ // Check if distributing cakes is possible
if (n > b) {
return -1;
}
// CakeList will store the number of students
// per cake of each class
vector< float > CakeList = ClassList;
// Initialize the number of cakes per class to 1
vector< float > CakePerClass(n, 1);
// Adjust available cakes for initial distribution
b = b - n;
// Distribute remaining cakes among classes
while (b > 0) {
// Decrease the number of remaining cakes
b--;
// Find the class with the maximum number of
// students per cake of each class
int ind
= max_element(CakeList.begin(), CakeList.end())
- CakeList.begin();
// Distribute a cake to the selected class
CakeList[ind]
= ClassList[ind] / (CakePerClass[ind] + 1);
// Increment the number of cakes for the class
CakePerClass[ind]++;
}
// Return the maximum number of students per cake
// after distributing all the cakes
return ceil (
*max_element(CakeList.begin(), CakeList.end()));
} int main()
{ int N = 1; // number of classes
int B = 2; // number of blueberry cakes
vector< float > ClassList
= { 35 }; // number of students in each class
// Call the distribution function and print the result
cout << distribution(N, B, ClassList) << endl;
return 0;
} // This code is contributed by the Author |
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
public class CakeDistribution {
public static int distribution( int n, int b, List<Float> classList) {
// Check if distributing cakes is possible
if (n > b) {
return - 1 ;
}
// CakeList will store the number of students
// per cake of each class
List<Float> cakeList = new ArrayList<>(classList);
// Initialize the number of cakes per class to 1
List<Float> cakePerClass = new ArrayList<>(Collections.nCopies(n, 1 .0f));
// Adjust available cakes for initial distribution
b = b - n;
// Distribute remaining cakes among classes
while (b > 0 ) {
// Decrease the number of remaining cakes
b--;
// Find the class with the maximum number of
// students per cake of each class
int ind = cakeList.indexOf(Collections.max(cakeList));
// Distribute a cake to the selected class
cakeList.set(ind, classList.get(ind) / (cakePerClass.get(ind) + 1 ));
// Increment the number of cakes for the class
cakePerClass.set(ind, cakePerClass.get(ind) + 1 );
}
// Return the maximum number of students per cake
// after distributing all the cakes
return ( int ) Math.ceil(Collections.max(cakeList));
}
public static void main(String[] args) {
int N = 1 ; // number of classes
int B = 2 ; // number of blueberry cakes
List<Float> classList = new ArrayList<>();
classList.add( 35 .0f); // number of students in each class
// Call the distribution function and print the result
System.out.println(distribution(N, B, classList));
}
} // This code is contributed by shivamgupta0987654321 |
# Python3 implementation of above approach import math
def distribution(n, b, ClassList):
# Check if distributing cakes is possible
if n > b:
return - 1
# ClassList will store number of students
# per cake of each class
CakeList = ClassList.copy()
# Initialize the number of cakes per class to 1
CakePerClass = [ 1 for i in range (n)]
# Adjust available cakes for initial distribution
b = b - n
# Distribute remaining cakes among classes
while b:
# Decrease the number of remaining cakes
b - = 1
# Find the class with maximum number of
# students per cake of each class
ind = CakeList.index( max (CakeList))
# Distribute a cake to the selected class
CakeList[ind] = ClassList[ind] / (CakePerClass[ind] + 1 )
# Increment the number of cakes for the class
CakePerClass[ind] + = 1
# Return the maximum number of students per cake
# after distributing all the cakes
return math.ceil( max (CakeList))
# Driver Code N = 1 # number of classes
B = 2 # number of blueberry cakes
ClassList = [ 35 ] # number of students in each class
# Call the distribution function and print the result print (distribution(N, B, ClassList))
# This code is contributed by the Author |
using System;
using System.Collections.Generic;
using System.Linq;
public class GFG
{ public static int Distribution( int n, int b, List< float > classList)
{
// Check if distributing cakes is possible
if (n > b)
{
return -1;
}
// CakeList will store the number of students
// per cake of each class
List< float > cakeList = new List< float >(classList);
// Initialize the number of cakes per class to 1
List< float > cakePerClass = Enumerable.Repeat(1.0f, n).ToList();
// Adjust available cakes for initial distribution
b = b - n;
// Distribute remaining cakes among classes
while (b > 0)
{
// Decrease the number of remaining cakes
b--;
// Find the class with the maximum number of
// students per cake of each class
int ind = cakeList.IndexOf(cakeList.Max());
// Distribute a cake to the selected class
cakeList[ind] = classList[ind] / (cakePerClass[ind] + 1);
// Increment the number of cakes for the class
cakePerClass[ind] += 1;
}
// Return the maximum number of students per cake
// after distributing all the cakes
return ( int )Math.Ceiling(cakeList.Max());
}
public static void Main( string [] args)
{
int N = 1; // number of classes
int B = 2; // number of blueberry cakes
List< float > classList = new List< float >();
classList.Add(35.0f); // number of students in each class
// Call the distribution function and print the result
Console.WriteLine(Distribution(N, B, classList));
}
} // This code is contributed by Rohit Singh |
// JavaScript code for the above approach: function distribution(n, b, classList) {
// Check if distributing cakes is possible
if (n > b) {
return -1;
}
// CakeList will store the number of students
// per cake of each class
let cakeList = [...classList];
// Initialize the number of cakes per class to 1
let cakePerClass = new Array(n).fill(1);
// Adjust available cakes for initial distribution
b = b - n;
// Distribute remaining cakes among classes
while (b > 0) {
// Decrease the number of remaining cakes
b--;
// Find the class with the maximum number of
// students per cake of each class
let ind = cakeList.indexOf(Math.max(...cakeList));
// Distribute a cake to the selected class
cakeList[ind] = classList[ind] / (cakePerClass[ind] + 1);
// Increment the number of cakes for the class
cakePerClass[ind]++;
}
// Return the maximum number of students per cake
// after distributing all the cakes
return Math.ceil(Math.max(...cakeList));
} // Driver Code const N = 1; // number of classes
const B = 2; // number of blueberry cakes
const ClassList = [35]; // number of students in each class
// Call the distribution function and print the result console.log(distribution(N, B, ClassList)); |
18
Time Complexity: O(N * B),
Auxiliary Space: O(N), where N is number of classes and B is number of blueberry cakes.
Efficient Approach: To solve the problem using Binary Search follow the below idea:
Instead of distributing cakes one by one, we can set a value for the “maximum students per cake” and then check if it’s possible to distribute the cakes in a way that meets this value. If we can achieve this distribution, we’ll increase the “maximum students per cake” and try again. Conversely, if we can’t achieve the desired distribution, we’ll decrease the “maximum students per cake” and attempt to find a feasible distribution.
- To do this we can use Binary Search by setting lower bound l to 1 as in the best case scenario we are able to distribute 1 cake per child, and upper bound r to maximum student count among classes as in the worst case scenario we will have to distribute 1 cake per class.
- Now In each iteration we will find a mid and then calculate the total number of cakes required and change the upper or lower bound accordingly.
- To calculate the total number of cakes required for the current mid value, iterate through each ClassList and determine how many cakes are needed to accommodate the students in that class while ensuring that each cake can have at most mid students. Sum up these calculations to obtain the total cakes required.
Below is the implementation of the above idea.
// C++ code for the above approach: #include <bits/stdc++.h> using namespace std;
int EfficientDistribution( int n, int b,
vector< int >& ClassList)
{ // Initialize the lower bound as 1
int l = 1;
// Set the upper bound as the maximum student count
// among classes
int r
= *max_element(ClassList.begin(), ClassList.end());
// Check if distributing cakes is not feasible due to
// inadequate cakes
if (b < n) {
return -1;
}
// Perform binary search to find the maximum students
// per cake
while (l < r) {
// Calculate the middle value of the current search
// range
int mid = (l + r) / 2;
// Initialize the total number of cakes required
int cakes_req = 0;
// Calculate the total required cakes for current
// students per cake value
for ( int i = 0; i < n; i++) {
cakes_req += ceil (( float )ClassList[i] / mid);
}
// Check if the current distribution is feasible
// within the given cake limit
if (cakes_req <= b) {
r = mid; // Update the upper bound
}
else {
l = mid + 1; // Update the lower bound
}
}
return r; // Return the maximum students per cake
} // Drivers code int main()
{ int N = 1; // Number of classes
int B = 2; // Number of blueberry cakes
vector< int > ClassList
= { 35 }; // Number of students in each class
// Call the EfficientDistribution function and print the
// result
cout << EfficientDistribution(N, B, ClassList) << endl;
return 0;
} // This code is contributed by the Author |
import java.util.ArrayList;
import java.util.Collections;
public class GFG {
static int efficientDistribution( int n, int b, ArrayList<Integer> classList) {
// Initialize the lower bound as 1
int l = 1 ;
// Set the upper bound as the maximum student count
// among classes
int r = Collections.max(classList);
// Check if distributing cakes is not feasible due to
// inadequate cakes
if (b < n) {
return - 1 ;
}
// Perform binary search to find the maximum students
// per cake
while (l < r) {
// Calculate the middle value of the current search
// range
int mid = (l + r) / 2 ;
// Initialize the total number of cakes required
int cakesReq = 0 ;
// Calculate the total required cakes for current
// students per cake value
for ( int i = 0 ; i < n; i++) {
cakesReq += Math.ceil(( double ) classList.get(i) / mid);
}
// Check if the current distribution is feasible
// within the given cake limit
if (cakesReq <= b) {
r = mid; // Update the upper bound
} else {
l = mid + 1 ; // Update the lower bound
}
}
return r; // Return the maximum students per cake
}
public static void main(String[] args) {
int N = 1 ; // Number of classes
int B = 2 ; // Number of blueberry cakes
ArrayList<Integer> classList = new ArrayList<>();
classList.add( 35 ); // Number of students in each class
// Call the efficientDistribution function and print the result
System.out.println(efficientDistribution(N, B, classList));
}
} // This code is contributed by rohit singh |
# Python3 implementation of above approach import math
def EfficientDistribution(n, b, ClassList):
# Initialize the lower bound as 1
l = 1
# Set the upper bound as the maximum student count among classes
r = max (ClassList)
# Check if distributing cakes is not feasible due to inadequate cakes
if b < n:
return "-1"
# Perform binary search to find the maximum students per cake
while l < r:
# Calculate the middle value of the current search range
mid = (l + r) / / 2
# Initialize the total number of cakes required
cakes_req = 0
# Calculate the total required cakes for current students per cake value
for i in range (n):
cakes_req + = math.ceil(ClassList[i] / mid)
# Check if the current distribution is feasible within the given cake limit
if cakes_req < = b:
r = mid # Update the upper bound
else :
l = mid + 1 # Update the lower bound
return r # Return the maximum students per cake
# Driver Code N = 1 # Number of classes
B = 2 # Number of blueberry cakes
ClassList = [ 35 ] # Number of students in each class
# Call the EfficientDistribution function and print the result print (EfficientDistribution(N, B, ClassList))
# This code is contributed by the Author |
using System;
using System.Collections.Generic;
using System.Linq;
class Program
{ static int EfficientDistribution( int n, int b, List< int > classList)
{
// Initialize the lower bound as 1
int l = 1;
// Set the upper bound as the maximum student count
// among classes
int r = classList.Max();
// Check if distributing cakes is not feasible due to
// inadequate cakes
if (b < n)
{
return -1;
}
// Perform binary search to find the maximum students
// per cake
while (l < r)
{
// Calculate the middle value of the current search
// range
int mid = (l + r) / 2;
// Initialize the total number of cakes required
int cakesReq = 0;
// Calculate the total required cakes for current
// students per cake value
foreach ( int students in classList)
{
cakesReq += ( int )Math.Ceiling(( double )students / mid);
}
// Check if the current distribution is feasible
// within the given cake limit
if (cakesReq <= b)
{
r = mid; // Update the upper bound
}
else
{
l = mid + 1; // Update the lower bound
}
}
return r; // Return the maximum students per cake
}
static void Main()
{
int N = 1; // Number of classes
int B = 2; // Number of blueberry cakes
List< int > classList = new List< int > { 35 }; // Number of students in each class
// Call the EfficientDistribution method and print the result
Console.WriteLine(EfficientDistribution(N, B, classList));
}
} |
// Javascript code for the above approach: function EfficientDistribution(n, b, ClassList) {
// Initialize the lower bound as 1
let l = 1;
// Set the upper bound as the maximum student count
// among classes
let r = ClassList.reduce((a, b) => Math.max(a, b), -Infinity);
// Check if distributing cakes is not feasible due to
// inadequate cakes
if (b < n) {
return -1;
}
// Perform binary search to find the maximum students
// per cake
while (l < r) {
// Calculate the middle value of the current search
// range
let mid = Math.trunc((l + r) / 2);
// Initialize the total number of cakes required
let cakes_req = 0;
// Calculate the total required cakes for current
// students per cake value
for (let i = 0; i < n; i++) {
cakes_req += Math.ceil(ClassList[i] / mid);
}
// Check if the current distribution is feasible
// within the given cake limit
if (cakes_req <= b) {
r = mid; // Update the upper bound
} else {
l = mid + 1; // Update the lower bound
}
}
return r; // Return the maximum students per cake
} // Drivers code let N = 1; // Number of classes
let B = 2; // Number of blueberry cakes
let ClassList = [35]; // Number of students in each class
// Call the EfficientDistribution function and print the // result console.log(EfficientDistribution(N, B, ClassList)); // This code is contributed by the ragul21 |
18
Time Complexity: O(N * log R),
Auxiliary Space: O(N), where N is number of classes and R is maximum student count among classes.