问题概述
给定一个非负索引 rowIndex,返回「杨辉三角」的第 rowIndex 行(从 0 开始索引)。
在杨辉三角中,每个数是它左上方和右上方的数的和。
可视化说明
杨辉三角(显示第 3 行)
第 0 行: 1
第 1 行: 1 1
第 2 行: 1 2 1
第 3 行: 1 3 3 1 ← 这是 rowIndex = 3 时返回的内容
第 4 行: 1 4 6 4 1
关键洞察
- 只需要返回一行,而不是整个三角形
- 第
rowIndex行有rowIndex + 1个元素 - 每个元素可以从上一行计算,或原地更新
解法 1:迭代(构建完整三角形)
工作原理
构建到 rowIndex 的所有行,然后返回最后一行:
python
class Solution:
def getRow(self, rowIndex):
if rowIndex == 0:
return [1]
triangle = []
for i in range(rowIndex + 1):
row = [1] * (i + 1)
for j in range(1, i):
row[j] = triangle[i - 1][j - 1] + triangle[i - 1][j]
triangle.append(row)
return triangle[rowIndex]
复杂度分析
- 时间复杂度: O(rowIndex²) - 构建到 rowIndex 的所有行
- 空间复杂度: O(rowIndex²) - 存储所有行
何时使用
- 直接的方法
- 易于理解
- 空间效率较低
解法 2:优化(单行更新)- 推荐
工作原理
从右到左原地更新单行:
python
class Solution:
def getRow(self, rowIndex):
row = [1] * (rowIndex + 1)
for i in range(1, rowIndex):
for j in range(i, 0, -1):
row[j] += row[j - 1]
return row
复杂度分析
- 时间复杂度: O(rowIndex²) - 仍需要更新所有元素
- 空间复杂度: O(rowIndex) - 只存储一行
何时使用
- 推荐 - 更节省空间
- 只存储一行而不是所有行
- 从右到左更新以避免覆盖所需值
关键洞察
不存储所有行,可以原地更新单行:
- 从全为 1 的行开始
- 对于从第 1 行到第 rowIndex-1 行的每个位置,从右到左更新元素
- 从右到左更新确保不会覆盖计算所需的值
为什么从右到左?
当更新 row[j] = row[j] + row[j-1] 时,我们需要 row[j-1] 的旧值。
- 如果从左到右:
row[j-1]在我们使用之前被更新 → 错误结果 - 如果从右到左:
row[j-1]仍然是旧值 → 正确结果
对比
| 方法 | 时间 | 空间 | 最佳适用 |
|---|---|---|---|
| 构建完整三角形 | O(rowIndex²) | O(rowIndex²) | 学习 - 更简单但占用更多空间 |
| 单行更新 | O(rowIndex²) | O(rowIndex) | 推荐 - 节省空间 |
总结
关键优化是从右到左原地更新单行,避免存储所有之前的行。这将空间复杂度从 O(rowIndex²) 降低到 O(rowIndex),同时保持相同的时间复杂度。