Fair Distribution of Cookies

MediumBacktracking · Bitmask DP🧩 Bitmask DPLeetCode #2305 ↗Updated

Problem

cookies[i] is the number of cookies in bag i. Hand every bag, unopened, to one of k children. The unfairness of a split is the largest total any child receives; return the minimum possible unfairness.
Input[8,15,10,20,8], k = 2Output31 (8+15+8 | 10+20)
Input[6,1,3,2,2,4,1,2], k = 3Output7

2 ≤ n ≤ 8  ·  1 ≤ cookies[i] ≤ 105  ·  2 ≤ k ≤ n

Try it yourself

Java
class Solution {
    public int distributeCookies(int[] cookies, int k) {
        
    }
}
Your code is saved in this browser.Submit on LeetCode ↗
Key insight
n ≤ 8 means the search space is tiny: either backtrack with strong pruning, or treat each child's share as a subset (bitmask) and do DP over “which bags are already handed out”.
PatternBitmask DP

Instinct n is tiny (about 20 or less) and you must use, visit or assign every item - make the set of used items a bitmask and DP over all 2^n subsets.

Memory hack Small n, big choice - let the bits keep score: each item is a light switch and the mask is the whole switch panel.

Open the Bitmask DP guide →

Approaches

Brute ForceTry Every Assignment

Time O(kn)Space O(n + k)

Give bag i to each child in turn and recurse, carrying the running maximum. At the end, the running max is that split's unfairness; keep the smallest. The recursion tree has kn leaves.

Java
private int best = Integer.MAX_VALUE;

public int distributeCookies(int[] cookies, int k) {
    dfs(cookies, new int[k], 0, 0);
    return best;
}
private void dfs(int[] cookies, int[] bins, int i, int curMax) {
    if (i == cookies.length) {
        best = Math.min(best, curMax);
        return;
    }
    for (int c = 0; c < bins.length; c++) {
        bins[c] += cookies[i];
        dfs(cookies, bins, i + 1, Math.max(curMax, bins[c]));
        bins[c] -= cookies[i];
    }
}

Simple and correct, but explores symmetric and hopeless branches.

At a glance

LevelApproachTimeSpace
Brute ForceTry Every AssignmentO(kn)O(n + k)
BetterBacktracking + Pruning + SymmetryO(kn) worstO(n + k)
OptimalBitmask DP over SubsetsO(k·3n)O(2n)
Common pitfalls
  • Greedy “give the bag to the poorest child” is not optimal (e.g. [3,3,2,2,2], k=2).
  • Breaking on an empty child before trying it — must try the first empty one once.
  • Recomputing the max over all k children at every leaf — carry curMax instead.
Interview tips
  • Read the constraints aloud: n ≤ 8 invites exponential search.
  • Explain the symmetry-breaking rule; it is the biggest practical speed-up.
  • Offer the bitmask DP for a guaranteed bound independent of kn.
Pattern
Partition into k groups minimising the max → backtracking with pruning, or subset/bitmask DP when n ≤ ~16.
My notes saved in this browser