给定一个非负索引 rowIndex
,返回「杨辉三角」的第 rowIndex
行。
在「杨辉三角」中,每个数是它左上方和右上方的数的和。
简单
点击在LeetCode中查看题目
输入:rowIndex = 3
输出:[1,3,3,1]
输入:rowIndex = 0
输出:[1]
输入:rowIndex = 1
输出:[1,1]
0 <= rowIndex <= 33
与第118题类似,我们可以逐行计算杨辉三角,直到计算到第rowIndex
行。不同的是,这里只需要返回最后一行,而不是整个三角形。
关键点:
具体步骤:
时间复杂度:O(rowIndex²),需要计算rowIndex+1行,每行最多有rowIndex+1个元素
空间复杂度:O(rowIndex),只需要存储最后一行
我们可以只使用一个数组来计算杨辉三角的每一行,通过从后向前更新数组来避免覆盖还未使用的值。
关键点:
具体步骤:
时间复杂度:O(rowIndex²),需要计算rowIndex+1行,每行最多有rowIndex+1个元素
空间复杂度:O(rowIndex),只需要一个长度为rowIndex+1的数组
杨辉三角的每一行实际上是二项式展开的系数,可以使用组合数公式直接计算。
关键点:
具体步骤:
时间复杂度:O(rowIndex),只需要计算rowIndex+1个元素
空间复杂度:O(rowIndex),需要一个长度为rowIndex+1的数组
以rowIndex = 4为例,计算第4行[1,4,6,4,1]的过程:
迭代 | row数组 | 更新过程 |
---|---|---|
初始化 | [1,0,0,0,0] | 初始化数组,第一个元素为1 |
i=1, j=1 | [1,1,0,0,0] | row[1] = row[1] + row[0] = 0 + 1 = 1 |
i=2, j=2 | [1,1,1,0,0] | row[2] = row[2] + row[1] = 0 + 1 = 1 |
i=2, j=1 | [1,2,1,0,0] | row[1] = row[1] + row[0] = 1 + 1 = 2 |
i=3, j=3 | [1,2,1,1,0] | row[3] = row[3] + row[2] = 0 + 1 = 1 |
i=3, j=2 | [1,2,3,1,0] | row[2] = row[2] + row[1] = 1 + 2 = 3 |
i=3, j=1 | [1,3,3,1,0] | row[1] = row[1] + row[0] = 2 + 1 = 3 |
i=4, j=4 | [1,3,3,1,1] | row[4] = row[4] + row[3] = 0 + 1 = 1 |
i=4, j=3 | [1,3,3,4,1] | row[3] = row[3] + row[2] = 1 + 3 = 4 |
i=4, j=2 | [1,3,6,4,1] | row[2] = row[2] + row[1] = 3 + 3 = 6 |
i=4, j=1 | [1,4,6,4,1] | row[1] = row[1] + row[0] = 3 + 1 = 4 |
最终结果:[1,4,6,4,1]
以rowIndex = 4为例,计算第4行[1,4,6,4,1]的过程:
j | 计算公式 | 结果 |
---|---|---|
0 | - | 1 |
1 | row[0] * (4-1+1) / 1 = 1 * 4 / 1 | 4 |
2 | row[1] * (4-2+1) / 2 = 4 * 3 / 2 | 6 |
3 | row[2] * (4-3+1) / 3 = 6 * 2 / 3 | 4 |
4 | row[3] * (4-4+1) / 4 = 4 * 1 / 4 | 1 |
最终结果:[1,4,6,4,1]
public class Solution {
// 方法一:逐行计算
public IList<int> GetRow(int rowIndex) {
IList<int> row = new List<int> { 1 };
for (int i = 1; i <= rowIndex; i++) {
List<int> newRow = new List<int>();
newRow.Add(1);
for (int j = 1; j < i; j++) {
newRow.Add(row[j - 1] + row[j]);
}
newRow.Add(1);
row = newRow;
}
return row;
}
// 方法二:空间优化的动态规划
public IList<int> GetRowOptimized(int rowIndex) {
int[] row = new int[rowIndex + 1];
row[0] = 1;
for (int i = 1; i <= rowIndex; i++) {
for (int j = i; j > 0; j--) {
row[j] += row[j - 1];
}
}
return row.ToList();
}
// 方法三:数学公式
public IList<int> GetRowMath(int rowIndex) {
List<int> row = new List<int>();
long val = 1;
row.Add(1);
for (int j = 1; j <= rowIndex; j++) {
val = val * (rowIndex - j + 1) / j;
row.Add((int)val);
}
return row;
}
}
class Solution:
# 方法一:逐行计算
def getRow(self, rowIndex: int) -> List[int]:
row = [1]
for i in range(1, rowIndex + 1):
new_row = [1]
for j in range(1, i):
new_row.append(row[j - 1] + row[j])
new_row.append(1)
row = new_row
return row
# 方法二:空间优化的动态规划
def getRowOptimized(self, rowIndex: int) -> List[int]:
row = [0] * (rowIndex + 1)
row[0] = 1
for i in range(1, rowIndex + 1):
for j in range(i, 0, -1):
row[j] += row[j - 1]
return row
# 方法三:数学公式
def getRowMath(self, rowIndex: int) -> List[int]:
row = [1]
val = 1
for j in range(1, rowIndex + 1):
val = val * (rowIndex - j + 1) // j
row.append(val)
return row
class Solution {
public:
// 方法一:逐行计算
vector<int> getRow(int rowIndex) {
vector<int> row = {1};
for (int i = 1; i <= rowIndex; i++) {
vector<int> newRow = {1};
for (int j = 1; j < i; j++) {
newRow.push_back(row[j - 1] + row[j]);
}
newRow.push_back(1);
row = newRow;
}
return row;
}
// 方法二:空间优化的动态规划
vector<int> getRowOptimized(int rowIndex) {
vector<int> row(rowIndex + 1, 0);
row[0] = 1;
for (int i = 1; i <= rowIndex; i++) {
for (int j = i; j > 0; j--) {
row[j] += row[j - 1];
}
}
return row;
}
// 方法三:数学公式
vector<int> getRowMath(int rowIndex) {
vector<int> row = {1};
long long val = 1;
for (int j = 1; j <= rowIndex; j++) {
val = val * (rowIndex - j + 1) / j;
row.push_back(val);
}
return row;
}
};
语言 | 执行用时 | 内存消耗 | 特点 |
---|---|---|---|
C# | 92 ms | 35.8 MB | 代码结构清晰,但性能较慢 |
Python | 28 ms | 15.0 MB | 代码简洁,性能适中 |
C++ | 0 ms | 6.4 MB | 执行速度最快,内存占用最少 |
解法 | 时间复杂度 | 空间复杂度 | 优点 | 缺点 |
---|---|---|---|---|
逐行计算 | O(rowIndex²) | O(rowIndex) | 实现简单,直观易懂 | 需要创建多个临时数组 |
空间优化的动态规划 | O(rowIndex²) | O(rowIndex) | 只需要一个数组,空间效率高 | 需要注意更新顺序 |
数学公式 | O(rowIndex) | O(rowIndex) | 计算最直接,效率最高 | 需要注意整数溢出问题 |