LeetCode 2929 - Distribute Candies Among Children II
The problem asks us to calculate the total number of ways to distribute n candies among exactly three children, with the constraint that no child can receive more than limit candies.
Difficulty: 🟡 Medium
Topics: Math, Combinatorics, Enumeration
Solution
Problem Understanding
The problem asks us to calculate the total number of ways to distribute n candies among exactly three children, with the constraint that no child can receive more than limit candies. Essentially, we are asked to enumerate all possible triplets (a, b, c) of non-negative integers that satisfy two conditions: a + b + c = n and 0 <= a, b, c <= limit. The output is the count of all such valid triplets.
The inputs are two positive integers. n represents the total number of candies available, which can be as large as 1,000,000. limit represents the maximum number of candies a single child can receive, which can also be as large as 1,000,000. These constraints imply that a naive enumeration of all possible combinations for large n would be computationally expensive.
Important edge cases include when n is very small (e.g., 1, 2, 3), when limit is smaller than n (forcing the distribution to respect the limit), or when limit is larger than n (allowing some children to receive zero candies). The problem guarantees that both inputs are positive integers, so we do not have to handle negative numbers or zero candies.
Approaches
Brute Force Approach
The brute-force solution involves iterating over all possible values for the first child from 0 to min(n, limit), for the second child also from 0 to min(n, limit), and calculating the third child's candies as n - a - b. If the third child’s value is non-negative and less than or equal to limit, the triplet is valid. We would count all such triplets.
This approach is correct because it explicitly enumerates all possibilities, but it has a worst-case time complexity of O(limit^2), which is too slow for the upper bounds of the problem (n and limit up to 1,000,000).
Optimal Approach
The key observation for optimization is that the number of valid triplets for a given a and b can be computed directly without iterating over c. Since c = n - a - b must satisfy 0 <= c <= limit, we know that for fixed a, b must lie in the range [max(0, n - limit - a), min(limit, n - a)]. Counting the number of integers in this range gives the number of valid b values for that a. Summing over all valid a values produces the total count.
This reduces the complexity from O(limit^2) to O(limit), which is acceptable given the constraints.
| Approach | Time Complexity | Space Complexity | Notes |
|---|---|---|---|
| Brute Force | O(limit^2) | O(1) | Enumerate all triplets explicitly |
| Optimal | O(limit) | O(1) | Use range calculation for b based on a to count valid triplets |
Algorithm Walkthrough
- Initialize a counter
total_waysto zero. - Loop over
afrom0tomin(n, limit). This represents the number of candies given to the first child. - For each
a, compute the valid range ofbusingb_min = max(0, n - limit - a)andb_max = min(limit, n - a). This ensures thatc = n - a - bis non-negative and does not exceedlimit. - If
b_min <= b_max, incrementtotal_waysbyb_max - b_min + 1, which is the number of validbvalues for the currenta. - After iterating all
a, returntotal_ways.
Why it works: The algorithm systematically counts all valid (a, b, c) triplets without iterating over c. For each a, it computes exactly how many b values lead to a valid c. The invariant is that for each iteration, all triplets counted satisfy both the total candy requirement and the per-child limit.
Python Solution
class Solution:
def distributeCandies(self, n: int, limit: int) -> int:
total_ways = 0
for a in range(min(n, limit) + 1):
b_min = max(0, n - limit - a)
b_max = min(limit, n - a)
if b_min <= b_max:
total_ways += b_max - b_min + 1
return total_ways
This implementation follows the optimal algorithm. We loop over all possible a values and compute the valid range of b that ensures c stays within bounds. For each a, the number of valid b values is added to total_ways. Finally, we return the accumulated total.
Go Solution
func distributeCandies(n int, limit int) int64 {
var totalWays int64 = 0
maxA := n
if limit < n {
maxA = limit
}
for a := 0; a <= maxA; a++ {
bMin := 0
if n-limit-a > 0 {
bMin = n - limit - a
}
bMax := n - a
if bMax > limit {
bMax = limit
}
if bMin <= bMax {
totalWays += int64(bMax - bMin + 1)
}
}
return totalWays
}
The Go version mirrors the Python approach. We explicitly handle integer arithmetic and cast the range difference to int64 to prevent overflow. Go does not need dynamic typing, so we compute the range using explicit max/min operations.
Worked Examples
Example 1: n = 5, limit = 2
| a | b_min | b_max | valid b count | total_ways |
|---|---|---|---|---|
| 0 | 3 | 2 | 0 | 0 |
| 1 | 2 | 2 | 1 | 1 |
| 2 | 1 | 2 | 2 | 3 |
Output: 3
Example 2: n = 3, limit = 3
| a | b_min | b_max | valid b count | total_ways |
|---|---|---|---|---|
| 0 | 0 | 3 | 4 | 4 |
| 1 | 0 | 2 | 3 | 7 |
| 2 | 0 | 1 | 2 | 9 |
| 3 | 0 | 0 | 1 | 10 |
Output: 10
Complexity Analysis
| Measure | Complexity | Explanation |
|---|---|---|
| Time | O(min(n, limit)) | Loop over a from 0 to min(n, limit) |
| Space | O(1) | Only a few integer variables are used, no extra data structures |
The loop over a is bounded by min(n, limit), and the computation for each a is constant time. Memory usage is minimal and does not scale with input.
Test Cases
# Provided examples
assert Solution().distributeCandies(5, 2) == 3 # Example 1
assert Solution().distributeCandies(3, 3) == 10 # Example 2
# Edge and boundary cases
assert Solution().distributeCandies(1, 1) == 1 # Only (1,0,0) permutations
assert Solution().distributeCandies(0, 1) == 1 # Only (0,0,0)
assert Solution().distributeCandies(6, 2) == 7 # Max per child is 2
assert Solution().distributeCandies(1000000, 1) == 0 # Cannot distribute more than limit
assert Solution().distributeCandies(3, 1000000) == 10 # Large limit, n small
| Test | Why |
|---|---|
n=5, limit=2 |
Checks normal small case with limit restricting distribution |
n=3, limit=3 |
Checks normal small case with limit not restrictive |
n=1, limit=1 |
Smallest positive n |
n=0, limit=1 |
No candies to distribute |
n=6, limit=2 |
Cannot assign more than limit to any child |
n=1000000, limit=1 |
Stress test, no solution possible |
n=3, limit=1000000 |
Large limit, small n, should count all combinations |
Edge Cases
One important edge case is when n is smaller than limit. In this case, the upper bound for each child is not restrictive, so we need to count all non-negative integer solutions summing to n. The algorithm correctly handles this because b_max is capped by min(limit, n-a).
Another edge case is when limit is smaller than n/3. This can make it impossible to distribute all candies evenly. The algorithm accounts for this by calculating b_min = max(0, n-limit-a), ensuring c does not exceed the limit.
A third edge case is when n is