🍬Beginner-Friendly Guide to Solving "Distribute Candies Among Children II" | LeetCode 2929 Explained (C++ | JavaScript | Python)
Om Shree

Om Shree @om_shree_0709

About: 🚀 Front-End Developer | UI/UX Enthusiast | EdTech Innovator I specialize in HTML5, CSS3, and JavaScript (ES6+), leveraging React.js ⚛️ and Tailwind CSS 🎨 to build scalable, high-performance web app

Location:
India
Joined:
Feb 27, 2025

🍬Beginner-Friendly Guide to Solving "Distribute Candies Among Children II" | LeetCode 2929 Explained (C++ | JavaScript | Python)

Publish Date: Jun 1
15 4

Distributing candies among children sounds simple, right? But what if there’s a limit on how many candies each child can get? Let’s break down this classic combinatorial problem and solve it efficiently!


Problem Statement

You are given two positive integers:

  • n = total candies
  • limit = maximum candies any child can receive

Goal: Find the total number of ways to distribute n candies among 3 children such that no child gets more than limit candies.


Example

  • Input: n = 5, limit = 2
  • Output: 3
  • Explanation: Valid distributions are (1, 2, 2), (2, 1, 2), and (2, 2, 1).

Step 1: Understand the Basics (Stars and Bars) ⭐✨

Without any limit, the problem reduces to distributing n identical candies into 3 children (bins), which can be done in:

Total ways = C(n + 3 - 1, 3 - 1) = C(n + 2, 2)
Enter fullscreen mode Exit fullscreen mode

Here, C(a, b) is the binomial coefficient "a choose b".

This formula comes from the Stars and Bars theorem:
Imagine n stars (candies) separated by 2 bars (dividers) that partition candies between the 3 children.


Step 2: Add the Limit Constraint Using Inclusion-Exclusion Principle 🔍

We must exclude all distributions where any child has more than limit candies.

Breakdown:

  • Let’s denote limit + 1 as L for simplicity.

  • Define sets:

    • A: Distributions where child 1 gets ≥ L candies
    • B: Distributions where child 2 gets ≥ L candies
    • C: Distributions where child 3 gets ≥ L candies

Our task: Count all distributions not in A ∪ B ∪ C.


Step 3: Use Inclusion-Exclusion Formula 🧮

We start with total distributions (no limits) and subtract distributions where the limit is exceeded:

Answer = Total - |A ∪ B ∪ C|
Enter fullscreen mode Exit fullscreen mode

By Inclusion-Exclusion:

|A ∪ B ∪ C| = |A| + |B| + |C| - |A ∩ B| - |B ∩ C| - |A ∩ C| + |A ∩ B ∩ C|
Enter fullscreen mode Exit fullscreen mode

Calculate Each Term:

  • Total (no limits):
  T = C(n + 2, 2)
Enter fullscreen mode Exit fullscreen mode
  • Number of distributions where one child exceeds the limit:

For child 1 exceeding limit, redefine candies:

  a' = a - L ≥ 0
Enter fullscreen mode Exit fullscreen mode

Remaining candies to distribute:

  n' = n - L
Enter fullscreen mode Exit fullscreen mode

Number of such distributions for one child:

  A = C(n' + 2, 2) = C(n - L + 2, 2)
Enter fullscreen mode Exit fullscreen mode

Since this applies to any of the 3 children:

  |A| + |B| + |C| = 3 × A
Enter fullscreen mode Exit fullscreen mode
  • Distributions where two children exceed the limit:

Similar reasoning:

  n'' = n - 2 × L
Enter fullscreen mode Exit fullscreen mode

Number of such distributions:

  B = C(n'' + 2, 2) = C(n - 2 × L + 2, 2)
Enter fullscreen mode Exit fullscreen mode

Number of pairs of children = 3

  |A ∩ B| + |B ∩ C| + |A ∩ C| = 3 × B
Enter fullscreen mode Exit fullscreen mode
  • Distributions where all three children exceed the limit:
  n''' = n - 3 × L
Enter fullscreen mode Exit fullscreen mode

Number of such distributions:

  C = C(n''' + 2, 2) = C(n - 3 × L + 2, 2)
Enter fullscreen mode Exit fullscreen mode

Step 4: Final Formula

Putting it all together:

Answer = T - 3 × A + 3 × B - C
Enter fullscreen mode Exit fullscreen mode

where:

T = C(n + 2, 2)
A = C(n - L + 2, 2)
B = C(n - 2 × L + 2, 2)
C = C(n - 3 × L + 2, 2)
Enter fullscreen mode Exit fullscreen mode

Step 5: Efficient Implementation in Code 💻

Let’s implement this in C++, JavaScript and Python.

C++

#include <iostream>
using namespace std;

long long comb(int n, int k) {
    if (k < 0 || k > n) return 0;
    long long res = 1;
    for (int i = 1; i <= k; ++i) {
        res = res * (n - i + 1) / i;
    }
    return res;
}

long long distributeCandies(int n, int limit) {
    int L = limit + 1;
    long long T = comb(n + 2, 2);
    long long A = comb(n - L + 2, 2);
    long long B = comb(n - 2 * L + 2, 2);
    long long C = comb(n - 3 * L + 2, 2);

    return T - 3 * A + 3 * B - C;
}

int main() {
    cout << distributeCandies(5, 2) << endl;  // Output: 3
    cout << distributeCandies(3, 3) << endl;  // Output: 10
    return 0;
}
Enter fullscreen mode Exit fullscreen mode

JavaScript

function comb(n, k) {
    if (k < 0 || k > n) return 0;
    let res = 1;
    for (let i = 1; i <= k; i++) {
        res *= (n - i + 1);
        res /= i;
    }
    return res;
}

function distributeCandies(n, limit) {
    const L = limit + 1;
    const T = comb(n + 2, 2);
    const A = comb(n - L + 2, 2);
    const B = comb(n - 2 * L + 2, 2);
    const C = comb(n - 3 * L + 2, 2);

    return T - 3 * A + 3 * B - C;
}

// Example:
console.log(distributeCandies(5, 2));  // Output: 3
console.log(distributeCandies(3, 3));  // Output: 10
Enter fullscreen mode Exit fullscreen mode

Python

def comb(n, k):
    if k < 0 or k > n:
        return 0
    res = 1
    for i in range(1, k + 1):
        res *= (n - i + 1)
        res //= i
    return res

def distribute_candies(n, limit):
    L = limit + 1
    T = comb(n + 2, 2)
    A = comb(n - L + 2, 2)
    B = comb(n - 2 * L + 2, 2)
    C = comb(n - 3 * L + 2, 2)

    return T - 3 * A + 3 * B - C

# Example:
print(distribute_candies(5, 2))  # Output: 3
print(distribute_candies(3, 3))  # Output: 10
Enter fullscreen mode Exit fullscreen mode

Conclusion 🎉

This problem is a great example of combining combinatorics with algorithmic optimization. The brute-force approach would be too slow for large inputs, but using the stars and bars theorem and the inclusion-exclusion principle, we can solve it efficiently in constant time after computing binomial coefficients.


Final Thoughts 🎯

  1. Using combinatorics and inclusion-exclusion allows for an O(1) time solution.

  2. Brute-force is inefficient for large inputs but okay for small values.

  3. This problem is a great example of applying mathematical thinking to optimize algorithms.


I hope this step-by-step explanation helps you understand how to tackle distribution problems with constraints. Feel free to share your thoughts or questions!

Comments 4 total

  • Anna kowoski
    Anna kowoskiJun 5, 2025

    Might be worth mentioning the trade-offs

  • Dotallio
    DotallioJun 5, 2025

    Really love how you made inclusion-exclusion so approachable here, and that constant time trick is awesome.
    Have you played with generalizing this to more than 3 children?

    • Om Shree
      Om ShreeJun 6, 2025

      Thank you so much for your kind words! 😊 I'm really glad the inclusion-exclusion breakdown and the constant-time optimization came through clearly, I wanted to make the math feel more intuitive and less intimidating.

      As for generalizing beyond 3 children, yes, it's definitely possible! The inclusion-exclusion principle scales well for k children, although the number of subsets (and terms) grows exponentially (2^k), which makes the implementation a bit more complex but still very systematic. It’s a fun challenge, and maybe something I could explore in a follow-up post!

      Thanks again for engaging, I truly appreciate it! 🙌

Add comment