Maximum number of groups that can receive fresh donuts distributed in batches of size K
Last Updated :
18 Oct, 2021
Given an array arr[] consisting of N positive integers such that arr[i] denotes the size of the ith group sitting in a donut shop and a positive integer K, which denotes the maximum number of donuts that can be served in a batch, the task is to find the maximum number of groups that can receive fresh donuts if the customers of the same group are served together.
Note: All the customers in a group do not receive leftover donuts from the previous batch.
Examples:
Input: arr[] = {1, 2, 3, 4, 5, 6}, K = 3
Output: 4
Explanation: One possible way for the ordering of the groups is {6, 2, 4, 5, 1, 3}.
- arr[0](= 6), The shops serve two batches of 3 donuts. So everyone gets fresh donuts.
- arr[1](= 2), The shop serves 3 fresh donuts, among which 1 gets left out. So everyone gets fresh donuts.
- arr[2](= 4), The shop serves first 1 leftover donut and then serves 3 fresh donuts.
- arr[1](= 5), The shop serves 6 fresh donuts, among which 1 is left out. So everyone gets fresh donuts.
- arr[1](= 1), The shop serves 1 leftover donut.
- arr[1](= 3), The shop serves 3 fresh donuts. So everyone gets fresh donuts.
Therefore, a total of 4 groups get fresh donuts which is the maximum possible number of groups.
Input: arr[] = {1, 3, 2, 5, 2, 2, 1, 6}, K = 4
Output: 4
Naive Approach: The given problem can be solved by using backtracking for all possible ordering based on the observation that the remainder of each group size by K, needs only to be considered. Follow the steps below to solve the problem:
- Initialize an array, say V[] of size K, where V[i] denotes the number of groups with i people remaining.
- Traverse the array, arr[] using the variable i and for each arr[i], increment the value of V[arr[i] % K] by 1.
- Define a recursive function say dfs(V, left) to where left is the number of leftover donuts from the previous batch:
- Initialize a variable, res as 0, to store the result of the current state.
- If the value of left is 0, then iterate in the range [1, K – 1] using the variable i and perform the following steps:
- Decrement the value of V[i] by 1 and recursively call the function with argument left-i.
- Update res to the maximum of dfs(V, left – i) + 1 and res.
- Increment the value of V[i] by 1 for the backtracking step.
- Otherwise, repeat the same steps as above, but in this case, do not add 1 to the result, since the selected group will get the leftover donut.
- Return the value of res.
- Call the recursive function defined above as dfs(V, 0) and store the returned value in a variable, say X.
- Finally, after completing the above steps, print the sum of V[0] and X as the result.
Below is the implementation of the above approach:
C++
#include <bits/stdc++.h>
using namespace std;
int dfs( int arr[], int left, int K)
{
int q = 0;
if (left == 0) {
for ( int i = 1; i < K; ++i) {
if (arr[i] > 0) {
arr[i]--;
q = max(q, 1 + dfs(arr, K - i, K));
arr[i]++;
}
}
}
else {
for ( int i = 1; i < K; ++i) {
if (arr[i] > 0) {
arr[i]--;
int nleft
= (i <= left ? left - i : K + left - i);
q = max(q, dfs(arr, nleft, K));
arr[i]++;
}
}
}
return q;
}
int maxGroups( int K, int arr[], int n)
{
int V[K] = { 0 };
for ( int x = 0; x < n; x++)
V[arr[x] % K]++;
int ans = V[0] + dfs(V, 0, K);
return ans;
}
int main()
{
int arr[] = { 1, 2, 3, 4, 5, 6 };
int n = sizeof (arr) / sizeof (arr[0]);
int K = 3;
cout << maxGroups(K, arr, n);
return 0;
}
|
Java
import java.io.*;
import java.util.*;
class GFG {
public static int dfs( int [] arr,
int left, int K)
{
int q = 0 ;
if (left == 0 ) {
for ( int i = 1 ; i < K; ++i) {
if (arr[i] > 0 ) {
arr[i]--;
q = Math.max(
q, 1 + dfs(arr, K - i, K));
arr[i]++;
}
}
}
else {
for ( int i = 1 ; i < K; ++i) {
if (arr[i] > 0 ) {
arr[i]--;
int nleft = (i <= left ? left - i
: K + left - i);
q = Math.max(q, dfs(arr, nleft, K));
arr[i]++;
}
}
}
return q;
}
public static int maxGroups( int K,
int [] arr)
{
int V[] = new int [K];
for ( int x : arr)
V[x % K]++;
int ans = V[ 0 ] + dfs(V, 0 , K);
return ans;
}
public static void main(String[] args)
{
int [] arr = { 1 , 2 , 3 , 4 , 5 , 6 };
int K = 3 ;
System.out.println(
maxGroups(K, arr));
}
}
|
Python3
def dfs(arr, left, K):
q = 0
if (left = = 0 ):
for i in range ( 1 ,K, 1 ):
if (arr[i] > 0 ):
arr[i] - = 1
q = max (q, 1 + dfs(arr, K - i, K))
arr[i] + = 1
else :
for i in range ( 1 ,K, 1 ):
if (arr[i] > 0 ):
arr[i] - = 1
nleft = left - i if i < = left else K + left - i
q = max (q, dfs(arr, nleft, K))
arr[i] + = 1
return q
def maxGroups(K, arr, n):
V = [ 0 for i in range (K)]
for x in range (n):
V[arr[x] % K] + = 1
ans = V[ 0 ] + dfs(V, 0 , K)
return ans
if __name__ = = '__main__' :
arr = [ 1 , 2 , 3 , 4 , 5 , 6 ]
n = len (arr)
K = 3
print (maxGroups(K, arr, n))
|
C#
using System;
class GFG{
public static int dfs( int [] arr,
int left, int K)
{
int q = 0;
if (left == 0)
{
for ( int i = 1; i < K; ++i)
{
if (arr[i] > 0)
{
arr[i]--;
q = Math.Max(q, 1 + dfs(arr, K - i, K));
arr[i]++;
}
}
}
else
{
for ( int i = 1; i < K; ++i)
{
if (arr[i] > 0)
{
arr[i]--;
int nleft = (i <= left ? left - i :
K + left - i);
q = Math.Max(q, dfs(arr, nleft, K));
arr[i]++;
}
}
}
return q;
}
public static int maxGroups( int K, int [] arr)
{
int [] V = new int [K];
foreach ( int x in arr)
V[x % K]++;
int ans = V[0] + dfs(V, 0, K);
return ans;
}
public static void Main( string [] args)
{
int [] arr = { 1, 2, 3, 4, 5, 6 };
int K = 3;
Console.WriteLine(maxGroups(K, arr));
}
}
|
Javascript
<script>
function dfs(arr, left, K)
{
let q = 0;
if (left == 0)
{
for (let i = 1; i < K; ++i)
{
if (arr[i] > 0)
{
arr[i]--;
q = Math.max(q, 1 + dfs(arr, K - i, K));
arr[i]++;
}
}
}
else
{
for (let i = 1; i < K; ++i)
{
if (arr[i] > 0)
{
arr[i]--;
let nleft = (i <= left ? left - i :
K + left - i);
q = Math.max(q, dfs(arr, nleft, K));
arr[i]++;
}
}
}
return q;
}
function maxGroups(K, arr, n)
{
let V = new Array(K).fill(0);
for (let x = 0; x < n; x++)
V[arr[x] % K]++;
let ans = V[0] + dfs(V, 0, K);
return ans;
}
let arr = [ 1, 2, 3, 4, 5, 6 ];
let n = arr.length;
let K = 3;
document.write(maxGroups(K, arr, n))
</script>
|
Time Complexity: O(N + KK)
Auxiliary Space: O(K)
Efficient Approach: The above approach has Optimal Substructure and Overlapping Subproblems, therefore, the above approach can also be optimized by memoizing the same recursive calls in a HashMap and use this state when the same problem is called recursively.
Below is the implementation of the above approach:
C++
#include <bits/stdc++.h>
using namespace std;
map<string, int > memo;
int dfs( int V[], int left, int K)
{
int q = 0;
string key = "" ;
for ( int i = 0; i < K; i++)
{
key = key + to_string(V[i]);
}
key += to_string(left);
if (memo.find(key) != memo.end())
return memo[key];
else if (left == 0) {
for ( int i = 1; i < K; ++i)
if (V[i] > 0) {
V[i]--;
q = max(q, 1 + dfs(V, K - i, K));
V[i]++;
}
}
else {
for ( int i = 1; i < K; ++i) {
if (V[i] > 0) {
V[i]--;
int nleft = i <= left ? left - i : K + left - i;
q = max(q, dfs(V, nleft, K));
V[i]++;
}
}
}
if (memo.find(key) != memo.end())
memo[key] = q;
else
memo[key] = q;
return q;
}
int maxGroups( int K, int arr[])
{
int V[K];
memset (V, 0, sizeof (V));
for ( int i = 0; i < 6; i++)
V[arr[i] % K]++;
int ans = V[0] + dfs(V, 0, K);
return ans;
}
int main()
{
int arr[] = { 1, 2, 3, 4, 5, 6 };
int K = 3;
cout << maxGroups(K, arr);
return 0;
}
|
Java
import java.io.*;
import java.util.*;
class GFG {
static HashMap<String, Integer> memo;
public static int dfs( int [] V,
int left, int K)
{
int q = 0 ;
String key = Arrays.toString(V);
key += Integer.toString(left);
if (memo.containsKey(key))
return memo.get(key);
else if (left == 0 ) {
for ( int i = 1 ; i < K; ++i)
if (V[i] > 0 ) {
V[i]--;
q = Math.max(
q, 1 + dfs(V, K - i, K));
V[i]++;
}
}
else {
for ( int i = 1 ; i < K; ++i) {
if (V[i] > 0 ) {
V[i]--;
int nleft = i <= left ? left - i
: K + left - i;
q = Math.max(q, dfs(V, nleft, K));
V[i]++;
}
}
}
memo.put(key, q);
return q;
}
public static int maxGroups( int K, int [] arr)
{
int V[] = new int [K];
for ( int x : arr)
V[x % K]++;
memo = new HashMap<String, Integer>();
int ans = V[ 0 ] + dfs(V, 0 , K);
return ans;
}
public static void main(String[] args)
{
int [] arr = { 1 , 2 , 3 , 4 , 5 , 6 };
int K = 3 ;
System.out.println(
maxGroups(K, arr));
}
}
|
Python3
memo = {}
def dfs(V, left, K):
q = 0
v = [ str ( int ) for int in V]
key = "," .join(v)
key + = str (left)
if key in memo:
return memo[key]
elif left = = 0 :
for i in range ( 1 , K):
if V[i] > 0 :
V[i] - = 1
q = max (q, 1 + dfs(V, K - i, K))
V[i] + = 1
else :
for i in range ( 1 , K):
if V[i] > 0 :
V[i] - = 1
if i < = left:
nleft = left - i
else :
nleft = K + left - i
q = max (q, dfs(V, nleft, K))
V[i] + = 1
if key in memo:
memo[key] = q
else :
memo[key] = q
return q
def maxGroups(K, arr):
V = [ 0 ] * (K)
for x in range ( len (arr)):
V[arr[x] % K] + = 1
memo = {}
ans = V[ 0 ] + dfs(V, 0 , K)
return ans
arr = [ 1 , 2 , 3 , 4 , 5 , 6 ]
K = 3
print (maxGroups(K, arr))
|
C#
using System;
using System.Collections.Generic;
public class GFG {
static Dictionary<String, int > memo;
public static int dfs( int [] V,
int left, int K)
{
int q = 0;
String key = string .Join( "," , V);
key += left.ToString();
if (memo.ContainsKey(key))
return memo[key];
else if (left == 0) {
for ( int i = 1; i < K; ++i)
if (V[i] > 0) {
V[i]--;
q = Math.Max(
q, 1 + dfs(V, K - i, K));
V[i]++;
}
}
else {
for ( int i = 1; i < K; ++i) {
if (V[i] > 0) {
V[i]--;
int nleft = i <= left ? left - i
: K + left - i;
q = Math.Max(q, dfs(V, nleft, K));
V[i]++;
}
}
}
if (memo.ContainsKey(key))
memo[key] = q;
else
memo.Add(key, q);
return q;
}
public static int maxGroups( int K, int [] arr)
{
int []V = new int [K];
foreach ( int x in arr)
V[x % K]++;
memo = new Dictionary<String, int >();
int ans = V[0] + dfs(V, 0, K);
return ans;
}
public static void Main(String[] args)
{
int [] arr = { 1, 2, 3, 4, 5, 6 };
int K = 3;
Console.WriteLine(
maxGroups(K, arr));
}
}
|
Javascript
<script>
let memo;
function dfs(V, left, K)
{
let q = 0;
let key = V.join( "," );
key += left.toString();
if (memo.has(key))
return memo[key];
else if (left == 0) {
for (let i = 1; i < K; ++i)
if (V[i] > 0) {
V[i]--;
q = Math.max(q, 1 + dfs(V, K - i, K));
V[i]++;
}
}
else {
for (let i = 1; i < K; ++i) {
if (V[i] > 0) {
V[i]--;
let nleft = i <= left ? left - i : K + left - i;
q = Math.max(q, dfs(V, nleft, K));
V[i]++;
}
}
}
if (memo.has(key))
memo[key] = q;
else
memo[key] = q;
return q;
}
function maxGroups(K, arr)
{
let V = new Array(K);
V.fill(0);
for (let x = 0; x < arr.length; x++)
V[arr[x] % K]++;
memo = new Map();
let ans = V[0] + dfs(V, 0, K);
return ans;
}
let arr = [ 1, 2, 3, 4, 5, 6 ];
let K = 3;
document.write(maxGroups(K, arr));
</script>
|
Time Complexity: O(N + K2)
Auxiliary Space: O(K)
Like Article
Suggest improvement
Share your thoughts in the comments
Please Login to comment...