Pascal's Triangle II - Complete Solution Guide
Pascal's Triangle II is LeetCode problem 119, a Easy level challenge. This complete guide provides step-by-step explanations, multiple solution approaches, and optimized code in python3, java, cpp, c.
Problem Statement
Given an integer rowIndex , return the rowIndex th ( 0-indexed ) row of the Pascal's triangle . In Pascal's triangle , each number is the sum of the two numbers directly above it as shown: Example 1: Input: rowIndex = 3 Output: [1,3,3,1] Example 2: Input: rowIndex = 0 Output: [1] Example 3: Input: rowIndex = 1 Output: [1,1] Constraints: 0 <= rowIndex <= 33 Follow up: Could you optimize your algorithm to use only O(rowIndex) extra space?
Detailed Explanation
This problem challenges us to extract a specific `rowIndex` (0-indexed) from Pascal's Triangle. Instead of generating the entire triangle, which can be memory-intensive for higher row indices, we're asked to return just that single target row as a list of integers. For instance, if `rowIndex` is 0, we expect `[1]`; if `rowIndex` is 1, `[1,1]`; and for `rowIndex = 3`, the output should be `[1,3,3,1]`. The core rule governing Pascal's Triangle is that each number is the sum of the two numbers directly above it, with the edges always being 1s.
Solution Approach
The provided solution elegantly computes the `rowIndex`th row using an in-place dynamic programming approach, adhering to an `O(rowIndex)` space complexity. It begins by initializing a list `row` of size `rowIndex + 1` with all ones. This clever initialization sets up the boundary elements correctly (the first and last numbers in any row of Pascal's Triangle are always 1) and provides a mutable structure for subsequent calculations. The algorithm then iterates with an outer loop that conceptually represents building the triangle row by row, up to our target. The inner loop, `for j in range(i, 0, -1)`, is crucial. It iterates *backwards* from `i` down to `1`, updating `row[j]` by adding `row[j-1]` to its current value. This backward iteration ensures that when `row[j]` is updated, `row[j-1]` still holds its value from the *previous conceptual row*, preventing us from using an already-updated value from the *current* iteration which would lead to incorrect sums. By working this way, the `row` list incrementally transforms, ultimately holding the correct values for the `rowIndex`th row.
Step-by-Step Algorithm
- Step 1: Initialize an array/list `row` of size `rowIndex + 1` with all elements set to 1.
- Step 2: Iterate from `i = 1` to `rowIndex - 1`. This loop represents each element's calculation in the row beyond the first and last which are already 1.
- Step 3: Inner loop iterates from `j = i` down to `1`. This iterates backward through the row calculating each element using the previous element in the array.
- Step 4: Inside the inner loop, add the previous element `row[j - 1]` to the current element `row[j]`. This updates the array in place.
- Step 5: After each row is generated, the last element (which is always 1) is added to the array.
- Step 6: Return the array `row` which holds the generated `rowIndex`-th row of Pascal's triangle.
Key Insights
- **In-place Calculation with Backward Iteration:** The core trick is updating the row in-place. The backward loop (`j` from `i` down to `1`) is essential. If `j` were to iterate forwards, `row[j-1]` would be updated before `row[j]` could use its *original* value, corrupting the sum. By going backwards, `row[j-1]` remains stable until `row[j]` has correctly utilized it.
- **Optimal Space Complexity (`O(k)`):** This solution uses only a single list of size `rowIndex + 1` to store the computed row. This means its space complexity is `O(rowIndex)`, directly satisfying the follow-up question for an optimized space usage. We avoid storing all preceding rows, which would incur `O(rowIndex^2)` space.
- **Smart Initialization:** Starting the `row` list with all ones (`[1] * (rowIndex + 1)`) is more than just a placeholder. It correctly sets the fixed '1's at the beginning and end of every row and provides base values for the intermediate sums. For `rowIndex` values of 0 or 1, this initialization alone is sufficient, as the loops won't even execute or will execute minimally to yield the correct result.
Complexity Analysis
Time Complexity: O(n^2)
Space Complexity: O(n)
Topics
This problem involves: Array, Dynamic Programming.
Companies
Asked at: Goldman Sachs, Yahoo.