Pascal's Triangle (LeetCode 118)
Build the top numRows rows of Pascal's triangle and hand them back.
Pascal's triangle's defining rule: every interior entry equals the two entries sitting directly above it, added together.
Worked Examples
numRows = 5[[1],[1,1],[1,2,1],[1,3,3,1],[1,4,6,4,1]]1, and every inner number is the sum of the two numbers above it.numRows = 1[[1]][1].⚖️Formal Constraints & Bounds
1 <= numRows <= 30
Core Insight
Each interior cell at row r and column c is the sum of the cells directly above it: triangle[r-1][c-1] + triangle[r-1][c]. Outer borders are always 1.
Real-World Scenario & Production Applications
Binomial coefficient lookups in probability theory, polynomial expansion algorithms, dynamic programming combinatorics.
The Math, Step by Step
1. The numbers in the triangle
Number the rows from 0 at the top, and the places in a row from 0 on the left. Row has numbers. Write for the number in row at place . The code stores it in triangle[r][c].
These numbers are the binomial coefficients: , the number of ways to choose items out of items. Part 3 shows why.
2. One entry from the row above
The problem's rule is that every inner entry is the sum of the two entries above it:
| Place in row | Value | In the code |
|---|---|---|
| , the left end | 1 | row = [1] * (r + 1) sets it |
| , the right end | 1 | row = [1] * (r + 1) sets it |
| , an inner place | row[c] = triangle[r - 1][c - 1] + triangle[r - 1][c] |
The two entries above place are place and place of row .
3. Why the entries are binomial coefficients
The binomial coefficients follow the same rule:
To see why, choose items out of items, and look at the last item. Either the choice includes the last item. Then the other items come from the first items, which gives ways. Or the choice leaves the last item out. Then all items come from the first items, which gives ways. The two groups do not overlap, and together they hold every choice.
The ends match too: , because there is one way to choose nothing and one way to choose everything. The triangle and the binomial coefficients start the same and grow by the same rule, so they are equal.
4. Rows 0 and 1, and why the code needs only additions
The inner loop is for c in range(1, r). For row 0 and row 1 this range is empty, so these rows stay all 1s: [1] and [1, 1]. From row 2 on, the loop fills places 1 to and leaves both ends at 1.
The code never computes a factorial. Each entry takes one addition of two numbers from the row above, which the code has already built. For the largest input, numRows = 30, the largest entry is , well inside a 32-bit integer.
5. Example 1 by hand
numRows = 5, so the code builds rows 0 to 4:
| Row | Inner entries computed | row |
|---|---|---|
| 0 | none | [1] |
| 1 | none | [1, 1] |
| 2 | [1, 2, 1] | |
| 3 | , | [1, 3, 3, 1] |
| 4 | , , | [1, 4, 6, 4, 1] |
The result is the expected output. Row 4 matches the formula: . Each row also adds up to : row 4 adds up to , the number of ways to choose any subset of 4 items.
6. Example 2 by hand
numRows = 1. The loop runs once, for row 0, which is [1]. The code returns [[1]], the expected output.
7. From the math to the code
| Math | In generate |
|---|---|
| rows | for r in range(numRows): |
row = [1] * (r + 1) | |
| inner places | for c in range(1, r): |
row[c] = triangle[r - 1][c - 1] + triangle[r - 1][c] |
The triangle has entries, and each takes one addition. So the code takes time and space.
| 1 | triangle = [] |
| 2 | for r in range(numRows): |
| 3 | row = [1] * (r + 1) |
| 4 | for c in range(1, r): |
| 5 | row[c] = prev[c-1] + prev[c] |
| 6 | triangle.append(row) |
| 7 | return triangle |
Conceptual Narrative
Pascal's Triangle generates binomial coefficients where each interior element is the sum of the two directly above it.
🧭 Conceptual Foundation & Pattern Intuition
Row in Pascal's Triangle represents the coefficients of the polynomial expansion . Each entry , with boundary values . Generating the triangle iteratively constructs each row in time from the preceding row.
🏟️ The Analogy: Water Cascading Down a Pyramid of Glasses
Imagine a pyramid of champagne glasses. Pouring into the top glass causes wine to overflow equally to the left and right glasses below. Each interior glass receives overflow from two glasses directly above it.
🔑 Why It Works
Padding boundaries with 1 and vectorizing pairwise additions builds each row in strictly linear time without factorial division.
Off-by-one on row indexing:
numRowsis 1-indexed (e.g.numRows = 5returns 5 rows). Off-by-one loops that stop atnumRows - 1miss the final row.Mutating previous row in-place: Reusing or mutating
prevwhile generatingcurrcorrupts subsequent column additions.Factorial overflow in combinatoric formulas: Computing directly causes 64-bit integer overflow even for moderate (). Addition-based DP avoids factorials entirely.
4-Phase Thought Process Model
Pattern Recognition Signals
The 10-second spot
Generate first numRows of Pascal's triangle, binomial coefficient grid, combinatorial pyramid.
Formulating the Predicate & Invariants
Turning intuition into a boolean rule
Invariant: In row r, row[0] = row[r] = 1, and for all 1 <= j < r, row[j] = prev[j - 1] + prev[j].
Silent Failure Traps & Edge Cases
Where confident candidates still lose points
Off-by-one row bounds: In row
r(0-indexed), there are exactlyr + 1elements. The interior loop runs fromj = 1tor - 1.Mutating the previous row in-place: Must construct a new list for each row to preserve previous rows in the output triangle.
Handling
numRows = 0ornumRows = 1: Ensure base cases return empty list or[[1]]cleanly without indexing out of bounds.
The 60-Second Interview Pitch
Say this out loud before you type a single line
I initialize
triangle = []. For each row indexrfrom 0 tonumRows - 1, I initialize a new row[1] * (r + 1). For every interior positionjfrom 1 tor - 1, I setrow[j] = triangle[r - 1][j - 1] + triangle[r - 1][j]. I appendrowtotriangleand return it. Total elements computed is N(N + 1)/2, running in O(numRows²) time and O(numRows²) space.
Complexity & Mathematical Proof
O(N^2)
Look at the execution steps: Row i has i elements. Row i is constructed by adding adjacent pairs from row i-1: row[j] = prev[j-1] + prev[j]. Total elements generated is 1 + 2 + ... + N = N * (N + 1) / 2 = O(N^2).
O(N^2) Auxiliary
Look at memory allocations: Call stack uses O(1) Iterative. Output 2D list stores N * (N + 1) / 2 integers total O(N^2) space.
T(N) = ∑_{i=1}^N i = (N(N+1) / 2) = O(N^2)
Derivation Progression
i elements in row i
Rows grow by 1 element per level.
row[j] = prev[j-1] + prev[j]
Each triangle cell computed in O(1) addition.
(N(N+1) / 2) = O(N^2)
Linear in size of triangle output.
Variable Definitions
Total number of rows in Pascal's triangle
Memory Architecture & Bounds
O(1) Iterative
O(1) Current row buffer (output list excluded)
O(N^2) 2D Pascal triangle array
Boundary Best / Worst Cases
Recurrence Tree Topology
Senior SWE Deconstruction & Hardware Caveats
Keyword trigger: "numRows", every entry equals the sum of the two entries just above it. Combinatorial trigger: Pascal's Identity . A Senior SWE recognizes 2D coordinate DP generation where each layer builds strictly upon the previous array.
. Total generated numbers: integers. Runtime and memory footprint are negligible ( with ).
returning [[1]]. Index out of bounds on interior pointers if not bounding .
Pascal's Triangle (LeetCode 118)
Build the top numRows rows of Pascal's triangle and hand them back.
Pascal's triangle's defining rule: every interior entry equals the two entries sitting directly above it, added together.
Worked Examples
numRows = 5[[1],[1,1],[1,2,1],[1,3,3,1],[1,4,6,4,1]]1, and every inner number is the sum of the two numbers above it.numRows = 1[[1]][1].⚖️Formal Constraints & Bounds
1 <= numRows <= 30
Core Insight
Each interior cell at row r and column c is the sum of the cells directly above it: triangle[r-1][c-1] + triangle[r-1][c]. Outer borders are always 1.
Real-World Scenario & Production Applications
Binomial coefficient lookups in probability theory, polynomial expansion algorithms, dynamic programming combinatorics.
The Math, Step by Step
1. The numbers in the triangle
Number the rows from 0 at the top, and the places in a row from 0 on the left. Row has numbers. Write for the number in row at place . The code stores it in triangle[r][c].
These numbers are the binomial coefficients: , the number of ways to choose items out of items. Part 3 shows why.
2. One entry from the row above
The problem's rule is that every inner entry is the sum of the two entries above it:
| Place in row | Value | In the code |
|---|---|---|
| , the left end | 1 | row = [1] * (r + 1) sets it |
| , the right end | 1 | row = [1] * (r + 1) sets it |
| , an inner place | row[c] = triangle[r - 1][c - 1] + triangle[r - 1][c] |
The two entries above place are place and place of row .
3. Why the entries are binomial coefficients
The binomial coefficients follow the same rule:
To see why, choose items out of items, and look at the last item. Either the choice includes the last item. Then the other items come from the first items, which gives ways. Or the choice leaves the last item out. Then all items come from the first items, which gives ways. The two groups do not overlap, and together they hold every choice.
The ends match too: , because there is one way to choose nothing and one way to choose everything. The triangle and the binomial coefficients start the same and grow by the same rule, so they are equal.
4. Rows 0 and 1, and why the code needs only additions
The inner loop is for c in range(1, r). For row 0 and row 1 this range is empty, so these rows stay all 1s: [1] and [1, 1]. From row 2 on, the loop fills places 1 to and leaves both ends at 1.
The code never computes a factorial. Each entry takes one addition of two numbers from the row above, which the code has already built. For the largest input, numRows = 30, the largest entry is , well inside a 32-bit integer.
5. Example 1 by hand
numRows = 5, so the code builds rows 0 to 4:
| Row | Inner entries computed | row |
|---|---|---|
| 0 | none | [1] |
| 1 | none | [1, 1] |
| 2 | [1, 2, 1] | |
| 3 | , | [1, 3, 3, 1] |
| 4 | , , | [1, 4, 6, 4, 1] |
The result is the expected output. Row 4 matches the formula: . Each row also adds up to : row 4 adds up to , the number of ways to choose any subset of 4 items.
6. Example 2 by hand
numRows = 1. The loop runs once, for row 0, which is [1]. The code returns [[1]], the expected output.
7. From the math to the code
| Math | In generate |
|---|---|
| rows | for r in range(numRows): |
row = [1] * (r + 1) | |
| inner places | for c in range(1, r): |
row[c] = triangle[r - 1][c - 1] + triangle[r - 1][c] |
The triangle has entries, and each takes one addition. So the code takes time and space.
| 1 | triangle = [] |
| 2 | for r in range(numRows): |
| 3 | row = [1] * (r + 1) |
| 4 | for c in range(1, r): |
| 5 | row[c] = prev[c-1] + prev[c] |
| 6 | triangle.append(row) |
| 7 | return triangle |
Conceptual Narrative
Pascal's Triangle generates binomial coefficients where each interior element is the sum of the two directly above it.
🧭 Conceptual Foundation & Pattern Intuition
Row in Pascal's Triangle represents the coefficients of the polynomial expansion . Each entry , with boundary values . Generating the triangle iteratively constructs each row in time from the preceding row.
🏟️ The Analogy: Water Cascading Down a Pyramid of Glasses
Imagine a pyramid of champagne glasses. Pouring into the top glass causes wine to overflow equally to the left and right glasses below. Each interior glass receives overflow from two glasses directly above it.
🔑 Why It Works
Padding boundaries with 1 and vectorizing pairwise additions builds each row in strictly linear time without factorial division.
Off-by-one on row indexing:
numRowsis 1-indexed (e.g.numRows = 5returns 5 rows). Off-by-one loops that stop atnumRows - 1miss the final row.Mutating previous row in-place: Reusing or mutating
prevwhile generatingcurrcorrupts subsequent column additions.Factorial overflow in combinatoric formulas: Computing directly causes 64-bit integer overflow even for moderate (). Addition-based DP avoids factorials entirely.
4-Phase Thought Process Model
Pattern Recognition Signals
The 10-second spot
Generate first numRows of Pascal's triangle, binomial coefficient grid, combinatorial pyramid.
Formulating the Predicate & Invariants
Turning intuition into a boolean rule
Invariant: In row r, row[0] = row[r] = 1, and for all 1 <= j < r, row[j] = prev[j - 1] + prev[j].
Silent Failure Traps & Edge Cases
Where confident candidates still lose points
Off-by-one row bounds: In row
r(0-indexed), there are exactlyr + 1elements. The interior loop runs fromj = 1tor - 1.Mutating the previous row in-place: Must construct a new list for each row to preserve previous rows in the output triangle.
Handling
numRows = 0ornumRows = 1: Ensure base cases return empty list or[[1]]cleanly without indexing out of bounds.
The 60-Second Interview Pitch
Say this out loud before you type a single line
I initialize
triangle = []. For each row indexrfrom 0 tonumRows - 1, I initialize a new row[1] * (r + 1). For every interior positionjfrom 1 tor - 1, I setrow[j] = triangle[r - 1][j - 1] + triangle[r - 1][j]. I appendrowtotriangleand return it. Total elements computed is N(N + 1)/2, running in O(numRows²) time and O(numRows²) space.
Complexity & Mathematical Proof
O(N^2)
Look at the execution steps: Row i has i elements. Row i is constructed by adding adjacent pairs from row i-1: row[j] = prev[j-1] + prev[j]. Total elements generated is 1 + 2 + ... + N = N * (N + 1) / 2 = O(N^2).
O(N^2) Auxiliary
Look at memory allocations: Call stack uses O(1) Iterative. Output 2D list stores N * (N + 1) / 2 integers total O(N^2) space.
T(N) = ∑_{i=1}^N i = (N(N+1) / 2) = O(N^2)
Derivation Progression
i elements in row i
Rows grow by 1 element per level.
row[j] = prev[j-1] + prev[j]
Each triangle cell computed in O(1) addition.
(N(N+1) / 2) = O(N^2)
Linear in size of triangle output.
Variable Definitions
Total number of rows in Pascal's triangle
Memory Architecture & Bounds
O(1) Iterative
O(1) Current row buffer (output list excluded)
O(N^2) 2D Pascal triangle array
Boundary Best / Worst Cases
Recurrence Tree Topology
Senior SWE Deconstruction & Hardware Caveats
Keyword trigger: "numRows", every entry equals the sum of the two entries just above it. Combinatorial trigger: Pascal's Identity . A Senior SWE recognizes 2D coordinate DP generation where each layer builds strictly upon the previous array.
. Total generated numbers: integers. Runtime and memory footprint are negligible ( with ).
returning [[1]]. Index out of bounds on interior pointers if not bounding .