Skip to content
dsa450for five year olds

Dynamic Programming · 3 of 60

Binomial Coefficient Problem

Count how many different groups of k friends you can pick from n friends, using a pyramid where every number is the sum of the two above it.

Simple way
time O(2^n)
room O(n)
Clever way
time O(n * k)
room O(k)

The problem, simply

You get two numbers, n and k. Count how many different groups of k things you can pick from n things. Order does not matter: picking Ann then Bob is the same group as Bob then Ann.

This count is written C(n, k) and is called "n choose k". The answer can be huge, so most judges want it modulo 10^9 + 7. If k is bigger than n, the answer is 0.

A story to remember it

Picture it

gridC(n, k)
k=0k=1k=2k=3k=4k=5n=0n=1n=2n=3n=4n=511112113311464115101051

The number pyramid (Pascal's triangle) in a table. Each box is the box above it plus the box above and to the left. Row 5, column 2 holds 10, the answer for picking 2 friends out of 5.

  • checking
  • answer

Examples

A normal case

In
n = 5, k = 2
Out
10

The 10 pairs are AB, AC, AD, AE, BC, BD, BE, CD, CE and DE.

Pick nobody

In
n = 4, k = 0
Out
1

There is exactly one way to pick nobody: the empty group.

Asking for too many

In
n = 3, k = 5
Out
0

You cannot pick 5 friends from 3. Return 0 instead of crashing.

Use the mirror

In
n = 10, k = 8
Out
45

Picking 8 to go is the same as picking 2 to stay home, so C(10, 8) = C(10, 2) = 45. Using the smaller k makes the work smaller.

Way 1: the simple way

Turn the story into a rule: C(n, k) = C(n - 1, k - 1) + C(n - 1, k). The first part is "the last friend comes", the second is "the last friend stays home".

  1. If k == 0 or k == n, there is one way. Return 1.
  2. Otherwise return C(n - 1, k - 1) + C(n - 1, k).
treecalls made by C(5,2)
C(5,2)C(4,1)C(3,0)C(3,1)C(2,0)C(2,1)C(1,0)C(1,1)C(4,2)C(3,1)C(2,0)C(2,1)C(1,0)C(1,1)C(3,2)C(2,1)C(1,0)C(1,1)C(2,2)againagainagainagainagainagainagainagain

Every call splits in two until it reaches an edge of the pyramid (double rings, worth 1). C(3,1) is worked out twice and C(2,1) three times. Each of them is the same question asked again.

  • seen
java
class Solution {
    public int nCr(int n, int k) {
        if (k > n) return 0;                    // cannot pick more than we have
        if (k == 0 || k == n) return 1;         // pick nobody, or pick everybody
        // last friend comes + last friend stays home
        return nCr(n - 1, k - 1) + nCr(n - 1, k);
    }
}

How long it takes: the calls branch in two, and the tree has about 2 * C(n, k) circles, which grows up to O(2^n). Extra room: the chain of waiting calls is at most n long, O(n).

Way 2: the clever way

The tree asks the same questions many times. Build the pyramid from the top instead, one row at a time. Row i only needs row i - 1, so keep one row in an array dp, where dp[j] is C(i, j).

  1. Start with dp = [1, 0, 0, ...]. That is row 0.
  2. For each row i from 1 to n, update dp[j] = dp[j] + dp[j - 1] for j going from right to left.
  3. The answer is dp[k].

Why right to left? dp[j] needs the old dp[j - 1], from the row above. If we went left to right we would have already changed it.

Build the pyramid row by row, keeping only one row

01 / 10

grid
k=0k=1k=2n=0n=1n=2n=3n=4n=51
arraydp (one row we keep)
012100

Row 0: from 0 friends you can pick 0 in one way, so C(0,0) = 1. The one-row array starts as 1, 0, 0.

  • checking
  • answer
  • just added
java
class Solution {
    public int nCr(int n, int k) {
        final long MOD = 1_000_000_007L;
        if (k > n) return 0;
        k = Math.min(k, n - k);               // picking k to go = picking n-k to stay
        long[] dp = new long[k + 1];          // dp[j] = C(row, j) for the current row
        dp[0] = 1;                            // row 0
        for (int i = 1; i <= n; i++) {
            // right to left, so dp[j - 1] still holds the row above
            for (int j = Math.min(i, k); j >= 1; j--) {
                dp[j] = (dp[j] + dp[j - 1]) % MOD;
            }
        }
        return (int) dp[k];
    }
}

How long it takes: n rows with at most k boxes each, O(n * k). Extra room: one row of k + 1 boxes, O(k).

Watch out for

  • k > n must give 0, and k = 0 must give 1.
  • Without the modulo, int overflows quickly. C(34, 17) is already more than 2 billion.
  • Do not compute n! / (k! * (n - k)!) with plain numbers. The factorials overflow long before the answer does.

What interviewers ask next

  • Can you do it in O(k) time without a table? Yes: start with res = 1 and for i = 0..k-1 do res = res * (n - i) / (i + 1). The division is always exact at each step, but it does not mix with a modulo.
  • Many queries with a prime modulo and n up to a million? Precompute factorials and their inverses with Fermat's little theorem (a^(p-2) mod p). Then each answer is O(1).
  • n is huge (like 10^18) and the prime p is small? Use Lucas' theorem: write n and k in base p and multiply the small binomials digit by digit.
  • Where else does this show up? Counting grid paths (C(m + n, n)), the number of subsets of size k, and the coefficients of (a + b)^n.

Remember this

Grown-up words: the number pyramid is Pascal's triangle, "n choose k" is the binomial coefficient, the repeated questions are overlapping subproblems, and keeping one row is a rolling array.