2929. Distribute Candies Among Children II
Problem Description
You have n
candies that need to be distributed among 3 children. Each child can receive between 0 and limit
candies (inclusive). Your task is to find the total number of different ways to distribute all n
candies such that no child receives more than limit
candies.
For example, if you have 5 candies and the limit is 2, you need to count all valid distributions where:
- Child 1 gets
a
candies (0 ≤a
≤ 2) - Child 2 gets
b
candies (0 ≤b
≤ 2) - Child 3 gets
c
candies (0 ≤c
≤ 2) - And
a + b + c = 5
The solution uses combinatorial mathematics with the principle of inclusion-exclusion. The approach treats this as a "stars and bars" problem where we distribute n
identical items into 3 distinct groups.
The formula C(n+2, 2)
represents all possible ways to distribute n
candies among 3 children without any restrictions. This uses the stars and bars method where we need 2 dividers to create 3 groups from n
items.
However, we must subtract cases where any child gets more than limit
candies. If one child gets more than limit
candies, we subtract 3 × C(n-limit+1, 2)
(accounting for each of the 3 children potentially exceeding the limit).
Since we might over-subtract cases where two children simultaneously exceed the limit, we add back 3 × C(n-2×limit, 2)
using the inclusion-exclusion principle.
The final answer gives the exact count of valid distribution methods.
Intuition
The key insight is recognizing this as a classic "stars and bars" combinatorial problem with constraints. When we need to distribute n
identical items (candies) among k
distinct groups (children), we can visualize this as arranging n
stars and k-1
bars in a line.
First, let's think about the unconstrained version. If we have n
candies and 3 children with no limits, we're essentially asking: "How many ways can we write n
as a sum of 3 non-negative integers?" This is equivalent to arranging n
stars and 2 bars, where the bars separate the stars into 3 groups. The formula for this is C(n+2, 2)
because we're choosing 2 positions for bars among n+2
total positions.
But our problem has a constraint: no child can get more than limit
candies. This is where the inclusion-exclusion principle becomes powerful.
Think of it this way:
- Start with all possible distributions:
C(n+2, 2)
- Some of these are "bad" because at least one child gets more than
limit
candies - We need to subtract these bad cases
To count the bad cases where child 1 gets more than limit
candies, we can "pre-allocate" limit+1
candies to child 1, then distribute the remaining n-(limit+1)
candies freely among all 3 children. This gives us C(n-limit+1, 2)
bad cases. Since any of the 3 children could be the one exceeding the limit, we multiply by 3.
However, when we subtract 3 × C(n-limit+1, 2)
, we've double-counted cases where TWO children both exceed the limit. These cases were subtracted twice (once for each child exceeding), so we need to add them back once. If two children each get limit+1
candies minimum, we have n-2(limit+1)
candies left to distribute, giving us C(n-2×limit, 2)
such cases. Again, there are 3 ways to choose which two children exceed the limit.
This inclusion-exclusion pattern ensures we count each valid distribution exactly once.
Learn more about Math and Combinatorics patterns.
Solution Approach
The implementation follows the inclusion-exclusion principle directly. Here's how the solution works step by step:
Step 1: Handle Edge Case
if n > 3 * limit: return 0
If the total candies n
exceeds 3 * limit
(the maximum possible distribution), it's impossible to distribute them within the constraints, so we return 0.
Step 2: Calculate Total Unrestricted Distributions
ans = comb(n + 2, 2)
Using the stars and bars formula, we calculate C(n+2, 2)
which represents all possible ways to distribute n
candies among 3 children without any restrictions. This is equivalent to choosing 2 positions for dividers among n+2
total positions (n candies + 2 dividers).
Step 3: Subtract Invalid Cases (One Child Exceeds Limit)
if n > limit: ans -= 3 * comb(n - limit + 1, 2)
When n > limit
, it's possible for a child to receive more than limit
candies. For each child that gets at least limit + 1
candies:
- We "reserve"
limit + 1
candies for that child - Distribute the remaining
n - (limit + 1) = n - limit - 1
candies among all 3 children - This gives
C(n - limit - 1 + 2, 2) = C(n - limit + 1, 2)
invalid distributions - Since any of the 3 children could be the one exceeding, multiply by 3
Step 4: Add Back Over-Subtracted Cases (Two Children Exceed Limit)
if n - 2 >= 2 * limit: ans += 3 * comb(n - 2 * limit, 2)
When n >= 2 * limit + 2
, it's possible for two children to simultaneously exceed the limit. These cases were subtracted twice in Step 3, so we add them back once:
- Two children each get at least
limit + 1
candies - We have
n - 2(limit + 1) = n - 2 * limit - 2
candies left to distribute - This gives
C(n - 2 * limit - 2 + 2, 2) = C(n - 2 * limit, 2)
such distributions - There are 3 ways to choose which 2 children exceed the limit (3 choose 2 = 3)
The final answer ans
gives the exact count of valid distributions where each child receives between 0 and limit
candies inclusive.
Note: The case where all three children exceed the limit is automatically handled because if n > 3 * limit
, we already returned 0 at the beginning.
Ready to land your dream job?
Unlock your dream job with a 5-minute evaluator for a personalized learning plan!
Start EvaluatorExample Walkthrough
Let's walk through a concrete example with n = 5
candies and limit = 2
.
We need to find all valid ways to distribute 5 candies among 3 children where each child gets at most 2 candies.
Step 1: Check if distribution is possible
- Is
n > 3 * limit
? Is5 > 6
? No, so we continue.
Step 2: Calculate total unrestricted distributions
- Using stars and bars:
C(n+2, 2) = C(7, 2) = 21
- This counts ALL ways to distribute 5 candies among 3 children without any limit.
- This includes invalid cases like (5,0,0), (4,1,0), (3,2,0), etc.
Step 3: Subtract cases where one child exceeds the limit
- Since
n = 5 > limit = 2
, we need to subtract invalid cases. - Cases where child 1 gets > 2 candies (i.e., at least 3):
- Pre-allocate 3 candies to child 1
- Distribute remaining 5-3=2 candies among all 3 children
- Number of ways:
C(2+2, 2) = C(4, 2) = 6
- These cases are: (3,2,0), (3,1,1), (3,0,2), (4,1,0), (4,0,1), (5,0,0)
- Similarly for child 2 and child 3 exceeding the limit
- Total to subtract:
3 * 6 = 18
- Running total:
21 - 18 = 3
Step 4: Add back cases where two children exceed the limit
- Check if
n - 2 >= 2 * limit
: Is3 >= 4
? No. - So no cases where two children both get > 2 candies are possible.
- Nothing to add back.
Final Answer: 3
Let's verify by listing all valid distributions:
- (2, 2, 1) - child 1 gets 2, child 2 gets 2, child 3 gets 1
- (2, 1, 2) - child 1 gets 2, child 2 gets 1, child 3 gets 2
- (1, 2, 2) - child 1 gets 1, child 2 gets 2, child 3 gets 2
Indeed, we have exactly 3 valid ways to distribute 5 candies with a limit of 2 per child!
The inclusion-exclusion principle correctly handled the overlapping constraints by:
- Starting with all 21 possible distributions
- Removing the 18 invalid cases where at least one child gets too many candies
- Resulting in the 3 valid distributions
Solution Implementation
1class Solution:
2 def distributeCandies(self, n: int, limit: int) -> int:
3 """
4 Calculate the number of ways to distribute n candies among 3 children
5 where each child can receive at most 'limit' candies.
6
7 Uses inclusion-exclusion principle to count valid distributions.
8
9 Args:
10 n: Total number of candies to distribute
11 limit: Maximum candies each child can receive
12
13 Returns:
14 Number of valid distributions
15 """
16 from math import comb
17
18 # If total candies exceed maximum possible (3 children * limit each)
19 # then no valid distribution exists
20 if n > 3 * limit:
21 return 0
22
23 # Start with total unrestricted distributions using stars and bars
24 # This is C(n+2, 2) - choosing 2 positions for dividers among n+2 positions
25 answer = comb(n + 2, 2)
26
27 # Subtract cases where at least one child gets more than limit candies
28 # Using inclusion-exclusion: subtract distributions where child i gets > limit
29 if n > limit:
30 # For each of 3 children, subtract cases where they get > limit candies
31 # If child i gets limit+1 or more, we distribute remaining n-(limit+1) candies
32 answer -= 3 * comb(n - limit + 1, 2)
33
34 # Add back cases where at least two children get more than limit candies
35 # (these were subtracted twice in the previous step)
36 if n - 2 >= 2 * limit:
37 # Cases where 2 children each get > limit candies
38 # They together get at least 2*(limit+1), leaving n-2*(limit+1) to distribute
39 answer += 3 * comb(n - 2 * limit, 2)
40
41 # Note: Cases where all 3 children get > limit are impossible since
42 # we already checked n <= 3*limit at the beginning
43
44 return answer
45
1class Solution {
2 /**
3 * Distributes n candies among 3 children where each child can receive at most 'limit' candies.
4 * Uses inclusion-exclusion principle to count valid distributions.
5 *
6 * @param n Total number of candies to distribute
7 * @param limit Maximum number of candies each child can receive
8 * @return Number of ways to distribute the candies
9 */
10 public long distributeCandies(int n, int limit) {
11 // If total candies exceed maximum possible distribution (3 children * limit each)
12 if (n > 3 * limit) {
13 return 0;
14 }
15
16 // Start with total unrestricted combinations: C(n+2, 2)
17 // This represents distributing n identical items into 3 distinct groups
18 long totalWays = calculateCombinationC2(n + 2);
19
20 // Subtract invalid cases where at least one child gets more than limit candies
21 // Using inclusion-exclusion: subtract cases where 1 child violates the limit
22 if (n > limit) {
23 // 3 ways to choose which child violates the limit
24 // For each, that child gets (limit + 1) or more candies
25 totalWays -= 3 * calculateCombinationC2(n - limit + 1);
26 }
27
28 // Add back cases where at least 2 children violate the limit (overcounted above)
29 // This corrects the inclusion-exclusion calculation
30 if (n - 2 >= 2 * limit) {
31 // 3 ways to choose which 2 children violate the limit
32 totalWays += 3 * calculateCombinationC2(n - 2 * limit);
33 }
34
35 return totalWays;
36 }
37
38 /**
39 * Calculates C(n, 2) = n choose 2 = n * (n-1) / 2
40 *
41 * @param n The number to calculate combination for
42 * @return The value of C(n, 2)
43 */
44 private long calculateCombinationC2(int n) {
45 return 1L * n * (n - 1) / 2;
46 }
47}
48
1class Solution {
2public:
3 long long distributeCandies(int n, int limit) {
4 // Lambda function to calculate C(n, 2) = n choose 2
5 // Returns the number of ways to choose 2 items from n items
6 auto calculateCombinationOfTwo = [](int n) {
7 return 1LL * n * (n - 1) / 2;
8 };
9
10 // If total candies exceed the maximum possible (3 children * limit each)
11 // then distribution is impossible
12 if (n > 3 * limit) {
13 return 0;
14 }
15
16 // Start with total ways to distribute n candies among 3 children
17 // Using stars and bars formula: C(n + 3 - 1, 3 - 1) = C(n + 2, 2)
18 long long totalWays = calculateCombinationOfTwo(n + 2);
19
20 // Apply inclusion-exclusion principle
21 // Subtract cases where at least one child gets more than limit candies
22 if (n > limit) {
23 // For each child that could exceed the limit
24 // Subtract C(n - limit - 1 + 2, 2) = C(n - limit + 1, 2)
25 // Multiply by 3 as any of the 3 children could exceed
26 totalWays -= 3 * calculateCombinationOfTwo(n - limit + 1);
27 }
28
29 // Add back cases where at least two children exceed the limit
30 // (these were subtracted twice in the previous step)
31 if (n - 2 >= 2 * limit) {
32 // If two children each get (limit + 1) candies minimum
33 // Remaining candies: n - 2 * (limit + 1) = n - 2 * limit - 2
34 // Add back C(n - 2 * limit - 2 + 2, 2) = C(n - 2 * limit, 2)
35 totalWays += 3 * calculateCombinationOfTwo(n - 2 * limit);
36 }
37
38 return totalWays;
39 }
40};
41
1/**
2 * Calculates the number of ways to distribute n candies among 3 children
3 * where each child can receive at most 'limit' candies.
4 *
5 * @param n - Total number of candies to distribute
6 * @param limit - Maximum number of candies each child can receive
7 * @returns The number of valid distributions
8 */
9function distributeCandies(n: number, limit: number): number {
10 /**
11 * Helper function to calculate combinations C(n, 2) = n * (n - 1) / 2
12 * Represents the number of ways to choose 2 items from n items
13 *
14 * @param n - Number of items to choose from
15 * @returns The number of combinations
16 */
17 const calculateCombinationOfTwo = (n: number): number => {
18 return (n * (n - 1)) / 2;
19 };
20
21 // If total candies exceed the maximum possible (3 children * limit each),
22 // no valid distribution exists
23 if (n > 3 * limit) {
24 return 0;
25 }
26
27 // Start with total ways to distribute n candies among 3 children
28 // using stars and bars formula: C(n + 3 - 1, 3 - 1) = C(n + 2, 2)
29 let totalWays: number = calculateCombinationOfTwo(n + 2);
30
31 // Apply inclusion-exclusion principle to subtract invalid cases
32 // where at least one child gets more than 'limit' candies
33 if (n > limit) {
34 // Subtract cases where at least one child gets more than limit
35 // For each child: C(n - limit - 1 + 2, 2) = C(n - limit + 1, 2)
36 // Multiply by 3 for all three children
37 totalWays -= 3 * calculateCombinationOfTwo(n - limit + 1);
38 }
39
40 // Add back cases that were over-subtracted (inclusion-exclusion)
41 // where at least two children get more than 'limit' candies
42 if (n - 2 >= 2 * limit) {
43 // Add back cases where at least two children exceed the limit
44 // C(n - 2 * limit - 2 + 2, 2) = C(n - 2 * limit, 2)
45 // Multiply by 3 for all combinations of two children
46 totalWays += 3 * calculateCombinationOfTwo(n - 2 * limit);
47 }
48
49 return totalWays;
50}
51
Time and Space Complexity
The time complexity is O(1)
because the algorithm performs a fixed number of operations regardless of the input size. The function executes at most:
- One comparison (
n > 3 * limit
) - One call to
comb(n + 2, 2)
- Two additional comparisons and conditional
comb
calculations
The comb
function (combination calculation) with arguments like comb(n + 2, 2)
computes (n + 2) * (n + 1) / 2
, which involves a constant number of arithmetic operations. Each comb
call takes O(1)
time since we're always choosing 2 items (the second parameter is fixed at 2).
The space complexity is O(1)
because the algorithm uses only a constant amount of extra space. It stores:
- The variable
ans
to accumulate the result - Temporary values during arithmetic calculations
- No additional data structures that scale with input size
All operations are performed using a fixed amount of memory regardless of the value of n
or limit
.
Learn more about how to find time and space complexity quickly.
Common Pitfalls
1. Incorrect Boundary Condition for Adding Back Over-Subtracted Cases
One of the most common mistakes is using the wrong condition for when to add back the over-subtracted cases in the inclusion-exclusion principle.
Incorrect Implementation:
if n - 2 >= 2 * limit: # Wrong condition! ans += 3 * comb(n - 2 * limit, 2)
The Problem:
The condition n - 2 >= 2 * limit
is checking if n >= 2 * limit + 2
, but this doesn't correctly identify when two children can simultaneously exceed the limit. For two children to each get more than limit
candies, they need at least 2 * (limit + 1) = 2 * limit + 2
candies total.
Correct Implementation:
if n > 2 * limit + 1: # Correct condition ans += 3 * comb(n - 2 * limit - 2, 2)
Or equivalently:
if n >= 2 * limit + 2: # Also correct ans += 3 * comb(n - 2 * limit - 2, 2)
2. Forgetting to Handle the Combination Function's Edge Cases
The comb(n, k)
function returns 0 when n < k
or when n < 0
, but relying on this behavior without explicit checks can lead to confusion and potential bugs.
Risky Implementation:
ans -= 3 * comb(n - limit + 1, 2) # What if n - limit + 1 < 2?
Better Implementation with Explicit Checks:
if n > limit: # Only subtract when it's actually possible for a child to exceed limit ans -= 3 * comb(n - limit + 1, 2) if n > 2 * limit + 1: # Only add back when it's possible for two children to exceed limit ans += 3 * comb(n - 2 * limit - 2, 2)
3. Off-by-One Errors in the Combinatorial Formula
A frequent mistake is incorrectly calculating the parameters for the combination function.
Common Mistakes:
# Wrong: forgetting to account for the "at least limit+1" constraint ans -= 3 * comb(n - limit, 2) # Should be comb(n - limit - 1 + 2, 2) # Wrong: incorrect stars and bars formula ans = comb(n + 3, 3) # Should be comb(n + 2, 2) for 3 children
Solution: Remember that when using stars and bars:
- For distributing
n
items intok
groups:C(n + k - 1, k - 1)
- When a child must get at least
m
candies, "reserve" thosem
candies first, then distribute the remainingn - m
candies
4. Not Considering All Edge Cases
Incomplete Edge Case Handling:
def distributeCandies(self, n: int, limit: int) -> int:
from math import comb
# Missing edge case check!
ans = comb(n + 2, 2)
ans -= 3 * comb(n - limit + 1, 2)
ans += 3 * comb(n - 2 * limit - 2, 2)
return ans
Complete Solution:
def distributeCandies(self, n: int, limit: int) -> int:
from math import comb
# Essential edge case: impossible distribution
if n > 3 * limit:
return 0
ans = comb(n + 2, 2)
# Only subtract if it's possible to exceed limit
if n > limit:
ans -= 3 * comb(n - limit - 1 + 2, 2)
# Only add back if two children can exceed limit
if n > 2 * limit + 1:
ans += 3 * comb(n - 2 * limit - 2 + 2, 2)
return ans
These pitfalls highlight the importance of careful analysis when implementing inclusion-exclusion principle solutions and properly handling boundary conditions in combinatorial problems.
Which of the following is a min heap?
Recommended Readings
Math for Technical Interviews How much math do I need to know for technical interviews The short answer is about high school level math Computer science is often associated with math and some universities even place their computer science department under the math faculty However the reality is that you
Backtracking Template Prereq DFS with States problems dfs_with_states Combinatorial search problems Combinatorial search problems involve finding groupings and assignments of objects that satisfy certain conditions Finding all permutations combinations subsets and solving Sudoku are classic combinatorial problems The time complexity of combinatorial problems often grows rapidly with the size of
Coding Interview Patterns Your Personal Dijkstra's Algorithm to Landing Your Dream Job The goal of AlgoMonster is to help you get a job in the shortest amount of time possible in a data driven way We compiled datasets of tech interview problems and broke them down by patterns This way
Want a Structured Path to Master System Design Too? Don’t Miss This!