LeetCode #118 Easy

Pascal's Triangle

Pascal's Triangle is LeetCode 118 (Easy). You are given an integer numRows and must return the first numRows rows of Pascal's triangle as a list of lists.

  • Row i (counting from 0) has i + 1 numbers.
  • The first and last number of every row is 1.
  • Every other number is the sum of the two numbers directly above it in the previous row.

numRows is between 1 and 30, so the whole triangle is at most 465 numbers. The Pascal's triangle LeetCode task is really about building each row cleanly from the one before it, not about speed.

Constraints
  • 1 <= numRows <= 30
arraydp
Open on LeetCode ↗
02

Intuition

Pascal's triangle explained in one sentence: every row is built from the row above it, and from nothing else. Each inner entry is the sum of the two entries above it, and both ends are always 1.

The Pascal triangle formula explains why the sum works. Entry j of row i is the binomial coefficient C(i, j) = i! / (j! (i − j)!), the number of ways to choose j items from i. Any such choice either includes the last item, leaving C(i−1, j−1) ways to pick the rest, or skips it, leaving C(i−1, j) ways. Those two counts are exactly the two numbers sitting above the entry.

How to spot this pattern

When each value in a table depends only on neighbours in the previous row, build it row by row and keep just the last row. Unique Paths (62) counts grid paths with the same addition, and any question about C(n, k) for small n can read the answer straight from the triangle.

03

Approach

Try it first

Before reading on, write row 5 using only row 4 ([1, 4, 6, 4, 1]). Then decide how many additions building numRows rows takes in total.

1

Start each row as all 1s

In the Pascal's triangle Python code, row i is created as [1] * (i + 1), a fresh list each time. That sets both ends correctly and leaves the inner slots to be overwritten. Rows 0 and 1 have no inner slots, so they are finished immediately.

2

Fill the inner entries from the previous row

For j from 1 to i − 1, set row[j] = prev[j - 1] + prev[j]. The previous row is already complete, so both parents are final, and reading from prev rather than the row being written means no value is overwritten before it is used.

3

Append and repeat

Append the finished row to the result and keep it as prev for the next row. After numRows rows, return the whole list. Each entry is computed once from two lookups, so time and output size are both O(numRows²).

04

Pascal's Triangle solution in Python | C++ | Java

▶1class Solution:
▶2 def generate(self, numRows: int) -> List[List[int]]:
▶3 triangle = []
▶4 for i in range(numRows):
▶5 row = [1] * (i + 1)
▶6 for j in range(1, i):
▶7 row[j] = triangle[i - 1][j - 1] + triangle[i - 1][j]
▶8 triangle.append(row)
▶9 return triangle
row01row1row2row3row4row 0 = [1]
i0row index
row[1]1 entries
Row 0 is [1]. Every row starts and ends with 1, and row i has i + 1 entries. Creating each row as all 1s handles both ends at once; only the inner entries need work.
row01row111row2row3row4row 1: both ends → [1, 1]
i1row index
row[1, 1]2 entries
Row 1 is [1, 1]. Both entries are ends, so there is nothing to add. The first sum appears in row 2.
row01row111row211row3row4row 2: ends = 1, 1 inner to fill
i2row index
row[1, ?, 1]3 entries
Start row 2 as 3 ones. The two ends are final: each has only one parent, a 1 on the edge of row 1. The single inner entry gets overwritten next.
row01row111row2121row3row41up-left+1up-right=2new entry
prev[0]1up-left
prev[1]1up-right
row[1]2
The rule: each inner entry is the sum of the two entries directly above it. Here 1 + 1 = 2. Both parents are already final, because row 1 was finished first.
row01row111row2121row311row4row 3: ends = 1, 2 inner to fill
i3row index
row[1, ?, ?, 1]4 entries
Start row 3 as 4 ones. The two ends are final: each has only one parent, a 1 on the edge of row 2. The 2 inner entries get overwritten next.
row01row111row2121row3131row41up-left+2up-right=3new entry
prev[0]1up-left
prev[1]2up-right
row[1]3
Up-left 1 plus up-right 2 gives 3. Think of it as counting paths down from the top: every path into this slot comes through exactly one of its two parents, so their counts add.
row01row111row2121row31331row42up-left+1up-right=3new entry
prev[1]2up-left
prev[2]1up-right
row[2]3
Up-left 2 plus up-right 1 gives 3. It mirrors row[1]: every row reads the same backwards, because C(3, 2) = C(3, 1).
row01row111row2121row31331row411row 4: ends = 1, 3 inner to fill
i4row index
row[1, ?, ?, ?, 1]5 entries
Start row 4 as 5 ones. The two ends are final: each has only one parent, a 1 on the edge of row 3. The 3 inner entries get overwritten next.
row01row111row2121row31331row41411up-left+3up-right=4new entry
prev[0]1up-left
prev[1]3up-right
row[1]4
Up-left 1 plus up-right 3 gives 4. Think of it as counting paths down from the top: every path into this slot comes through exactly one of its two parents, so their counts add.
row01row111row2121row31331row414613up-left+3up-right=6new entry
prev[1]3up-left
prev[2]3up-right
row[2]6
Up-left 3 plus up-right 3 gives 6. This is the middle of the row, the largest value in it.
row01row111row2121row31331row4146413up-left+1up-right=4new entry
prev[2]3up-left
prev[3]1up-right
row[3]4
Up-left 3 plus up-right 1 gives 4. It mirrors row[1]: every row reads the same backwards, because C(4, 3) = C(4, 1).
sum11sum211sum4121sum81331sum1614641return all 5 rows
rows5
last row[1, 4, 6, 4, 1]
Done. Each entry was one addition, so 5 rows cost O(numRows²). Each row sums to a power of 2, because every entry is added into exactly two children. Entry j of row i is the binomial coefficient C(i, j): the number of ways to choose j items from i.
05

Common pitfalls

Looping j over the ends too

✗ Wrong
for j in range(0, i + 1):
    row[j] = prev[j - 1] + prev[j]
✓ Right
for j in range(1, i):
    row[j] = prev[j - 1] + prev[j]

At j = 0, prev[-1] silently reads the last element in Python, and at j = i, prev[i] is out of range. The ends have only one parent, so they stay 1.

Sharing one list between rows

✗ Wrong
row = [1]
for i in range(numRows):
    triangle.append(row)
    row.append(1)
✓ Right
for i in range(numRows):
    row = [1] * (i + 1)
    triangle.append(row)

Appending the same list object means every row in the result is the same list, and all of them show the last row. Each row must be a new list.

Computing each entry from factorials

✗ Wrong
row[j] = factorial(i) // (factorial(j) * factorial(i - j))
✓ Right
row[j] = prev[j - 1] + prev[j]

It is O(i) work per entry instead of O(1), and in C++ or Java the factorials overflow long before the entries do: 21! does not fit in 64 bits, while row 30 still fits in an int.

06

Complexity

Time
O(numRows²)
Space
O(numRows²)
The triangle has 1 + 2 + … + numRows ≈ numRows²/2 entries and each takes one addition. The output itself is that size, so no approach can do better.
07

Pascal's Triangle vs Pascal's Triangle II

LeetCode has two versions. The rule is the same; what they return, and so what memory they need, differs.

Pascal's Triangle (118)Pascal's Triangle II (119)
Returnsall rows 0 to numRows − 1only row rowIndex
MemoryO(n²), the outputO(n): one row updated in place
In-place tricknot neededupdate row[j] += row[j-1] from right to left
Direct formulanot neededC(n, k+1) = C(n, k) × (n − k) / (k + 1)
08

Pascal's Triangle FAQ

What is Pascal's triangle?

A triangle of numbers where each row starts and ends with 1 and every inner number is the sum of the two above it. Row n lists the binomial coefficients C(n, 0) to C(n, n). It is named after Blaise Pascal, though it was known centuries earlier in India, Persia and China.

What patterns are in Pascal's triangle?
  • Each row reads the same forwards and backwards.
  • Row n sums to 2ⁿ.
  • The second diagonal is 1, 2, 3, 4…, the third is the triangular numbers 1, 3, 6, 10….
  • Row n gives the coefficients of (a + b)ⁿ, the binomial theorem.
  • Rows 0 to 4 read as numbers are powers of 11: 1, 11, 121, 1331, 14641.
What is Pascal's triangle used for?

Expanding (a + b)ⁿ, counting combinations C(n, k), probabilities for coin flips (row n counts the ways to get k heads in n flips), and counting lattice paths through a grid.