Nth Row of Pascal Triangle
Given a row index n, return just that single row of Pascal's Triangle, without producing every row that comes above it.
Do this lesson first: climbing stairsExample input
n = 8
Expected output
1 8 28 56 70 56 28 8 1
Break it down
Answer each question out loud before you open it. Getting it wrong here is the useful part. A revealed answer you never guessed at teaches you nothing.
Fill the table
The table pauses before each cell you have to supply. Type the value the recurrence gives, and the write animation confirms it.
Press start. The animation stops at every cell YOUR recurrence must fill.
dp[n][0] = 1 and dp[n][n] = 1 on every row, one way to choose nothing and one way to choose everything, and both must be given rather than summed because the cells the rule would reach for, column -1 at one end and a position above the diagonal at the other, are off the table. Now say what that means HERE, because it is not what it means on binomial-coefficient's page, where the bases are the two places the answer is not. TWO OF THE NUMBERS THIS PAGE RETURNS ARE BASES. The 1 at each end of row 8 was not worked out by the sweep, it was handed to it, and only the 7 interior entries of the answer row are computed at all. Of the 45 live cells at n = 8, 17 are given, one per row down the left edge and one per row past the first on the diagonal, and 28 are summed. The positions above the diagonal show a dot, meaning a position that does not exist rather than a zero, and nothing here could read one even by accident: a computed cell in row r at column k has k <= r - 1, so the two cells it reads are columns k - 1 and k of row r - 1, both on or below that row's own diagonal. The FILL ORDER is that page's order too, and it is what this page's whole objection is about. Row-major, top to bottom and left to right inside each row, is enough for the rule, though it is not the only order that would do (column-major satisfies the same dependencies), and it is exactly the order the statement objects to: reaching row 8 this way means writing all 36 cells of rows 0 through 7, and 21 of those are additions this order performs before the first interior entry of row 8 is reached. None of the 36 is wanted. The order is not wrong. It is the cost, and execution is where that gets settled.
- 1
function pascalsTriangleRow(n) { - 2
const dp = Array.from({ length: n + 1 }, () => new Array(n + 1).fill(0)); - 3
for (let i = 0; i <= n; i++) { - 4
dp[i][0] = 1; - 5
dp[i][i] = 1; - 6
for (let k = 1; k < i; k++) { - 7
const keepIt = dp[i - 1][k - 1]; - 8
const dropIt = dp[i - 1][k]; - 9
dp[i][k] = keepIt + dropIt; - 10
} - 11
} - 12
return dp[n]; - 13
}
The code, the trap, the variations
- 1
function pascalsTriangleRow(n) { - 2
const dp = Array.from({ length: n + 1 }, () => new Array(n + 1).fill(0)); - 3
for (let i = 0; i <= n; i++) { - 4
dp[i][0] = 1; - 5
dp[i][i] = 1; - 6
for (let k = 1; k < i; k++) { - 7
const keepIt = dp[i - 1][k - 1]; - 8
const dropIt = dp[i - 1][k]; - 9
dp[i][k] = keepIt + dropIt; - 10
} - 11
} - 12
return dp[n]; - 13
}
Where people go wrong
Updating the single rolling row from the LEFT. It is the one step of the reduction that has a direction, and going the wrong way fails silently: nothing throws, the values stay whole numbers, and they are simply the wrong whole numbers. Writing row[k] = row[k] + row[k - 1] with k running upwards means position k - 1 has already been overwritten with the new row's value by the time position k reads it, so the cell adds its NEW left neighbour instead of the old one the rule asked for. At n = 8 that returns 1, 8, 35, 110, 275, 572, 1001, 1430, 1430 where the row is 1, 8, 28, 56, 70, 56, 28, 8, 1: too large from column 2 rightwards, no longer symmetric, and no longer even ending in a 1. What makes this survive a glance is that the wrong numbers are not noise. Run the broken loop for n = 1 through 8 and its last entry comes out 1, 2, 5, 14, 42, 132, 429, 1430, which are the Catalan numbers, so what comes back is a real and recognisable integer sequence rather than obvious garbage. Run the inner loop downwards from k = i instead and every cell reads the old value it wanted, with no second buffer. A smaller trap worth naming: the 1s at the two ends of the row are given, not computed, so a loop that tries to compute every entry of row n uniformly will ask for column -1 at one end and a position above the diagonal at the other.
Return the whole triangle down to row n instead of just row n.
Nothing about the recurrence, the bases or the fill order moves, and the O(n^2) sweep on this page stops being the wasteful choice: every cell it writes is now part of the answer, so the output has grown to the size of the table and the objection this whole page is built around disappears. Both reductions above die with it, because neither the rolling row nor the in-row closed form keeps the rows it has already finished. This is a catalog problem in its own right, pascals-triangle, and it is left statement-only rather than authored for a reason worth knowing: its answer is the entire table, so there is no single cell to highlight and no answer cell an independent check could ever disagree with.
Return row n modulo a prime p, the usual competitive-programming form.
Take a % p after each addition and every cell stays below p, which removes the overflow question entirely and leaves shape, bases, order and dependency arrows untouched. This is also the variation that makes the table worth keeping rather than the closed form: the in-row step divides by k, and dividing modulo p means multiplying by the modular inverse of k, which is real extra machinery to get right. The additive row needs a plus and a percent.
Ask for a single entry of the row rather than the whole row.
That is binomial-coefficient, the same table read at one highlighted cell instead of across the bottom row, and as problems they differ in nothing else. The two PAGES differ in one thing, which is what they open the slider at: 6 there against 8 here, so that two neighbouring pages never show the same grid. Going that way also revives a reduction this page cannot use: a sweep that only needs column k can stop at that column, which is O(n k) rather than O(n^2). The whole row needs every column of the bottom row, so it needs the whole triangle, and O(n k) with k = n is O(n^2) again.