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
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".
- If
k == 0ork == n, there is one way. Return 1. - Otherwise return
C(n - 1, k - 1) + C(n - 1, k).
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
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).
- Start with
dp = [1, 0, 0, ...]. That is row 0. - For each row
ifrom 1 ton, updatedp[j] = dp[j] + dp[j - 1]forjgoing from right to left. - 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
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
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 > nmust give 0, andk = 0must give 1.- Without the modulo,
intoverflows 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 withres = 1and fori = 0..k-1dores = 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
nup to a million? Precompute factorials and their inverses with Fermat's little theorem (a^(p-2) mod p). Then each answer isO(1). nis huge (like10^18) and the primepis small? Use Lucas' theorem: writenandkin basepand 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 sizek, 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.