Facebook Pixel

2226. Maximum Candies Allocated to K Children

Problem Description

You have an array candies where each element candies[i] represents a pile of candies with that many candies in it. You need to distribute these candies to k children following these rules:

  1. Equal distribution: Every child must receive exactly the same number of candies
  2. Pile division: You can split any pile into smaller sub-piles (for example, a pile of 10 candies can be split into piles of 7 and 3, or 5 and 5, etc.)
  3. No merging: You cannot combine different piles together
  4. Single pile per child: Each child can only receive candies from one pile (either an original pile or a sub-pile you created)
  5. Not all piles need to be used: Some piles can remain unallocated

Your goal is to find the maximum number of candies that each child can receive while satisfying all these constraints.

For example, if you have candies = [5, 8, 6] and k = 3 children:

  • You could give each child 5 candies by dividing the pile of 8 into 5 and 3, then giving one child the pile of 5, another child the sub-pile of 5, and the third child another pile of 5 from the pile of 6
  • You cannot give each child 6 candies because you can only create two piles of size 6 or larger

The solution uses binary search to find the maximum candies per child. The key insight is that if it's possible to give each child v candies, then it's also possible to give each child any amount less than v. The algorithm searches for the highest valid value by checking if we can create at least k piles of size mid from the available candies using the formula sum(x // mid for x in candies) >= k.

Quick Interview Experience
Help others by sharing your interview experience
Have you seen this problem before?

Intuition

The problem has a monotonic property: if we can give each child v candies, we can definitely give them any amount less than v. This suggests binary search.

The pattern for this problem is: true, true, ..., true, false, false - we want to find the maximum value where the condition is true (can serve k children).

To use the standard first_true_index template, we invert the condition. Instead of asking "can we serve k children?", we ask "is it impossible to serve k children?":

infeasible(v) = sum(pile // v for pile in candies) < k

This creates the pattern: false, false, ..., false, true, true

  • For small values of v, we can serve k children → infeasible = false
  • For large values of v, we cannot serve k children → infeasible = true

The first_true_index gives us the first value where we cannot serve k children. The maximum valid answer is therefore first_true_index - 1.

Edge case: If first_true_index = 1, it means we can't even give 1 candy to each child, so the answer is 0.

The search space is bounded:

  • left = 1: Minimum meaningful candy amount (0 is always valid but trivial)
  • right = max(candies) + 1: We search up to max+1 to handle the case where max(candies) itself is valid

Learn more about Binary Search patterns.

Solution Implementation

1class Solution:
2    def maximumCandies(self, candies: List[int], k: int) -> int:
3        # Infeasible function: returns True when we CANNOT serve k children
4        def infeasible(v: int) -> bool:
5            portions = sum(pile // v for pile in candies)
6            return portions < k
7
8        # Binary search setup
9        left = 1  # Minimum candy amount
10        right = max(candies) + 1  # Extended upper bound
11        first_true_index = 1  # Default: infeasible starts at 1 (answer would be 0)
12
13        # Binary search for the first infeasible value
14        while left <= right:
15            mid = (left + right) // 2
16            if infeasible(mid):
17                first_true_index = mid  # Found infeasible value
18                right = mid - 1  # Find smaller infeasible value
19            else:
20                left = mid + 1  # mid is feasible, try larger
21
22        # Maximum feasible = first infeasible - 1
23        return first_true_index - 1
24
1class Solution {
2    public int maximumCandies(int[] candies, long k) {
3        // Find max pile size for upper bound
4        int maxPile = 0;
5        for (int pile : candies) {
6            maxPile = Math.max(maxPile, pile);
7        }
8
9        // Binary search setup
10        int left = 1;
11        int right = maxPile + 1;  // Extended upper bound
12        int firstTrueIndex = 1;  // Default: infeasible starts at 1
13
14        // Binary search for the first infeasible value
15        while (left <= right) {
16            int mid = left + (right - left) / 2;
17
18            // Check if infeasible: cannot serve k children with mid candies
19            if (infeasible(candies, mid, k)) {
20                firstTrueIndex = mid;
21                right = mid - 1;  // Find smaller infeasible value
22            } else {
23                left = mid + 1;  // mid is feasible, try larger
24            }
25        }
26
27        // Maximum feasible = first infeasible - 1
28        return firstTrueIndex - 1;
29    }
30
31    // Returns true when we CANNOT serve k children with v candies each
32    private boolean infeasible(int[] candies, int v, long k) {
33        long portions = 0;
34        for (int pile : candies) {
35            portions += pile / v;
36        }
37        return portions < k;
38    }
39}
40
1class Solution {
2public:
3    int maximumCandies(vector<int>& candies, long long k) {
4        // Find max pile for upper bound
5        int maxPile = *max_element(candies.begin(), candies.end());
6
7        // Binary search setup
8        int left = 1;
9        int right = maxPile + 1;  // Extended upper bound
10        int firstTrueIndex = 1;  // Default: infeasible starts at 1
11
12        // Infeasible function: returns true when we CANNOT serve k children
13        auto infeasible = [&](int v) -> bool {
14            long long portions = 0;
15            for (int pile : candies) {
16                portions += pile / v;
17            }
18            return portions < k;
19        };
20
21        // Binary search for the first infeasible value
22        while (left <= right) {
23            int mid = left + (right - left) / 2;
24
25            if (infeasible(mid)) {
26                firstTrueIndex = mid;
27                right = mid - 1;  // Find smaller infeasible value
28            } else {
29                left = mid + 1;  // mid is feasible, try larger
30            }
31        }
32
33        // Maximum feasible = first infeasible - 1
34        return firstTrueIndex - 1;
35    }
36};
37
1function maximumCandies(candies: number[], k: number): number {
2    // Infeasible function: returns true when we CANNOT serve k children
3    const infeasible = (v: number): boolean => {
4        let portions = 0;
5        for (const pile of candies) {
6            portions += Math.floor(pile / v);
7        }
8        return portions < k;
9    };
10
11    // Binary search setup
12    const maxPile = Math.max(...candies);
13    let left = 1;
14    let right = maxPile + 1;  // Extended upper bound
15    let firstTrueIndex = 1;  // Default: infeasible starts at 1
16
17    // Binary search for the first infeasible value
18    while (left <= right) {
19        const mid = Math.floor((left + right) / 2);
20
21        if (infeasible(mid)) {
22            firstTrueIndex = mid;
23            right = mid - 1;  // Find smaller infeasible value
24        } else {
25            left = mid + 1;  // mid is feasible, try larger
26        }
27    }
28
29    // Maximum feasible = first infeasible - 1
30    return firstTrueIndex - 1;
31}
32

Solution Approach

We use the binary search template with an inverted condition to find the maximum candies per child.

Defining the Infeasible Function:

We invert the problem to use the first_true_index template:

infeasible(v) = sum(pile // v for pile in candies) < k

This returns true when we cannot serve k children with v candies each.

Binary Search Setup:

  • left = 1: Minimum candy amount to check
  • right = max(candies) + 1: Upper bound (we extend by 1 to handle edge cases)
  • first_true_index = 1: Default to 1 (meaning even 1 candy is infeasible → answer is 0)

Binary Search Template:

left, right = 1, max(candies) + 1
first_true_index = 1  # Default: infeasible starts at 1

while left <= right:
    mid = (left + right) // 2
    if infeasible(mid):  # Cannot serve k children
        first_true_index = mid
        right = mid - 1  # Find smaller infeasible value
    else:
        left = mid + 1  # mid is still feasible, try larger

return first_true_index - 1  # Maximum feasible = first infeasible - 1

Why This Works:

  • When infeasible(mid) is true, we found where things break; try smaller values
  • When infeasible(mid) is false, mid works; try larger values
  • The answer is first_true_index - 1 (the last value before things became infeasible)

Time Complexity: O(n × log(max(candies))) where n is the length of the candies array.

Space Complexity: O(1) - only constant extra space used.

Ready to land your dream job?

Unlock your dream job with a 5-minute evaluator for a personalized learning plan!

Start Evaluator

Example Walkthrough

Let's trace through with candies = [5, 8, 6] and k = 3.

Infeasible function: infeasible(v) = (5//v + 8//v + 6//v) < 3

Initialize:

  • left = 1, right = max(5, 8, 6) + 1 = 9
  • first_true_index = 1 (default)

Iteration 1: left = 1, right = 9

  • mid = (1 + 9) // 2 = 5
  • Portions: 5//5 + 8//5 + 6//5 = 1 + 1 + 1 = 3
  • infeasible(5) = (3 < 3)false (we CAN serve 3 children)
  • left = 5 + 1 = 6

Iteration 2: left = 6, right = 9

  • mid = (6 + 9) // 2 = 7
  • Portions: 5//7 + 8//7 + 6//7 = 0 + 1 + 0 = 1
  • infeasible(7) = (1 < 3)true (we CANNOT serve 3 children)
  • first_true_index = 7, right = 7 - 1 = 6

Iteration 3: left = 6, right = 6

  • mid = (6 + 6) // 2 = 6
  • Portions: 5//6 + 8//6 + 6//6 = 0 + 1 + 1 = 2
  • infeasible(6) = (2 < 3)true (we CANNOT serve 3 children)
  • first_true_index = 6, right = 6 - 1 = 5

Termination: left = 6 > right = 5, exit loop

Result: first_true_index - 1 = 6 - 1 = 5

Verification:

  • At v=5: portions = 3 ≥ 3 ✓ (feasible)
  • At v=6: portions = 2 < 3 ✗ (infeasible)
  • Maximum candies per child = 5

Time and Space Complexity

The time complexity is O(n × log M), where n is the length of the array candies, and M is the maximum value in the array candies. This complexity arises from:

  • Binary search performs O(log M) iterations, as we search in the range [0, max(candies)]
  • In each iteration, we calculate sum(x // mid for x in candies), which takes O(n) time to iterate through all elements

The space complexity is O(1), as the algorithm only uses a constant amount of extra space for variables l, r, and mid, regardless of the input size.

Learn more about how to find time and space complexity quickly.

Common Pitfalls

1. Using Wrong Binary Search Template Variant

A common mistake is using the standard "find maximum feasible" pattern instead of inverting to first_true_index.

Wrong approach:

while left < right:
    mid = (left + right + 1) // 2
    if feasible(mid):
        left = mid  # Wrong pattern
    else:
        right = mid - 1
return left

Correct approach (inverted condition):

first_true_index = 1  # Default
while left <= right:
    mid = (left + right) // 2
    if infeasible(mid):  # Cannot serve k children
        first_true_index = mid
        right = mid - 1
    else:
        left = mid + 1
return first_true_index - 1  # Maximum feasible

2. Division by Zero Error

Starting with left = 0 causes division by zero when mid = 0.

Solution: Always start with left = 1:

left = 1  # Not 0!
right = max(candies) + 1

3. Forgetting to Extend Upper Bound

If max(candies) itself is valid (all piles can contribute 1 portion of that size), we need to check beyond it to find where things become infeasible.

Solution: Use right = max(candies) + 1:

right = max(candies) + 1  # Not just max(candies)

4. Edge Case: More Children than Total Candies

If k > sum(candies), even giving 1 candy each is impossible.

Solution: The template handles this naturally - first_true_index will be 1, so answer is 0.

Loading...
Discover Your Strengths and Weaknesses: Take Our 5-Minute Quiz to Tailor Your Study Plan:

What data structure does Breadth-first search typically uses to store intermediate states?


Recommended Readings

Want a Structured Path to Master System Design Too? Don’t Miss This!

Load More