13. nCr

The problem can be found at the following link: 🔗 Question Link

🧩 Problem Description

Given two integers n and r, return the value of the binomial coefficient C(n, r), defined as the number of ways to choose r objects from a set of n without regard to order. It is given by:

C(n,r)=n!r!(nr)!C(n, r) = \frac{n!}{r!\,(n-r)!}

If $r > n$, return 0. It is guaranteed that the result will fit within a 32-bit integer.

📘 Examples

Example 1:

Input:

n = 5, r = 2

Output:

10

Explanation:

C(5,2)=5!2!3!=1202×6=10C(5,2) = \frac{5!}{2!\,3!} = \frac{120}{2\times6} = 10

Example 2:

Input:

Output:

Explanation:

Since $r > n$, $C(2,4)=0$.

Example 3:

Input:

Output:

Explanation:

C(5,0)=5!0!5!=1.C(5,0) = \frac{5!}{0!\,5!} = 1.

🔒 Constraints

  • $1 \leq n \leq 100$

  • $0 \leq r \leq 100$

✅ My Approach

Modular Inverse + Factorials

We compute factorials up to n modulo $10^9+7$, then use Fermat’s little theorem to find modular inverses in $O(n + \log(\text{MOD}))$:

  1. Precompute fact[i] = i! mod MOD for $0 \le i \le n$.

  2. Compute inv[n] = fact[n]^(MOD-2) mod MOD via fast exponentiation.

  3. Build inv[i-1] = inv[i] * i mod MOD for $i = n$ down to 1 (inverse factorials).

  4. Return

    C(n,r)=fact[n]×inv[r]×inv[nr] mod MOD.C(n,r) = fact[n] \times inv[r] \times inv[n-r]\ \bmod\ \text{MOD}.

Algorithm Steps:

  1. Handle if $r > n$: return 0.

  2. Initialize constants: MOD = 10^9+7.

  3. Allocate two arrays of size n+1: fact[], inv[].

  4. Compute factorials:

  5. Compute inverse factorial of n:

    using binary exponentiation in $O(\log,\text{MOD})$.

  6. Compute remaining inverses:

  7. Combine:

🧮 Time and Auxiliary Space Complexity

  • Expected Time Complexity: $O(n + \log(\text{MOD}))$, since we build factorials in $O(n)$, compute one modular exponentiation in $O(\log,\text{MOD})$, and build inverse factorials in $O(n)$.

  • Expected Auxiliary Space Complexity: $O(n)$, for storing fact[] and inv[] arrays of size $n+1$.

🧠 Code (C++)

⚡ Alternative Approaches

📊 2️⃣ DP Table (Pascal’s Triangle)

Idea

Use the identity $C(i, j) = C(i-1, j-1) + C(i-1, j)$ to build a DP table of size $(n+1)\times(r+1)$.

Algorithm Steps

  1. Allocate C[n+1][r+1], initialize with zeros.

  2. For each i in 0..n:

    • For each j in 0..min(i,r):

      • If j == 0 or j == i: C[i][j]=1.

      • Else: C[i][j] = (C[i-1][j-1] + C[i-1][j]) % MOD.

  3. Return C[n][r].

⏱️ Time: $O(n \times r)$ 🗂️ Space: $O(n \times r)$

📊 3️⃣ Recursive + Memoization

Idea

Use recursion on the identity $C(n,r)=C(n-1,r-1)+C(n-1,r)$ with memoization to avoid recomputation.

Algorithm Steps

  1. Base: if r == 0 or r == n, return 1.

  2. If dp[n][r] is cached, return it.

  3. Otherwise compute (solve(n-1,r-1) + solve(n-1,r)) % MOD, store in dp[n][r].

⏱️ Time: $O(n \times r)$ 🗂️ Space: $O(n \times r)$

🆚 Comparison of Approaches

Approach

⏱️ Time

🗂️ Space

Pros

⚠️ Cons

Modular Inverse + Factorials

🟢 $O(n + \log,\text{MOD})$

🟢 $O(n)$

Fast; handles large $n$; reusable

Requires mod exponentiation step

DP Table

🔸 $O(n \times r)$

🔸 $O(n \times r)$

Simple; no exponentiation

Higher time/memory for large inputs

Recursive + Memoization

🔸 $O(n \times r)$

🔸 $O(n \times r)$

Elegant recursion

Recursion/memo overhead; risk of stack

Best Choice?

Use Case

Recommended Approach

Single query or multiple large queries

🥇 Modular Inverse + Factorials

Educational/demo or small $n,r$

🥈 DP Table

Academic demonstration of recursion

🥉 Recursive + Memoization

🧑‍💻 Code (Java)

🐍 Code (Python)

🧠 Contribution and Support

For discussions, questions, or doubts related to this solution, feel free to connect on LinkedIn: 📬 Any Questions?. Let’s make this learning journey more collaborative!

If you find this helpful, please give this repository a star!


📍Visitor Count

Last updated