力扣-119. 杨辉三角 II
1.题目
题目地址(119. 杨辉三角 II - 力扣(LeetCode))
https://leetcode.cn/problems/pascals-triangle-ii/
题目描述
给定一个非负索引 rowIndex
,返回「杨辉三角」的第 rowIndex
行。
在「杨辉三角」中,每个数是它左上方和右上方的数的和。
示例 1:
输入: rowIndex = 3 输出: [1,3,3,1]
示例 2:
输入: rowIndex = 0 输出: [1]
示例 3:
输入: rowIndex = 1 输出: [1,1]
提示:
0 <= rowIndex <= 33
进阶:
你可以优化你的算法到 O(rowIndex)
空间复杂度吗?
2.题解
2.1 滚动数组
思路
针对118中使用二维数组进行了较小优化,只保存当前层和上一层的数据
代码
- 语言支持:C++
C++ Code:
class Solution {
public:
vector<int> getRow(int rowIndex) {
vector<int> prev, cur;
for(int i = 0; i <= rowIndex; i++){
cur.resize(i + 1);
cur[0] = cur[i] = 1;
for(int j = 1; j < i; j++){
cur[j] = prev[j] + prev[j-1];
}
prev = cur;
}
return cur;
}
};
复杂度分析
令 n 为数组长度。
- 时间复杂度:\(O(rowIndex^2)\)
- 空间复杂度:\(O(n)\)
2.2 一个数组(倒算)
思路
简化空间复杂度为O(1)? 如何实现?
我们思考 row[i][j] = row[i-1][j] + row[i-1][j-1];
在由第i-1行到第i行的过程中, 我们能否直接根据该层状态进行原地更新?
从前向后更新肯定是不行的, 由于每次计算 row[j] = row[j] + row[j-1] 中需要利用到j-1, 但是我们刚计算完前面的值就将其覆盖掉了
那我们思考,能否进行倒算呢?从该行本来应该的最后一个位置向前倒算即可!!!
代码
class Solution {
public:
vector<int> getRow(int rowIndex) {
vector<int> row(rowIndex + 1);
row[0] = 1;
for(int i = 1; i <= rowIndex; i++){
for(int j = i; j > 0; j--){
row[j] += row[j - 1];// 由于公式是row[i-1][j] + row[i-1][j-1], 需要用到前面一行的数据,从后向前加就不会覆盖数据了,而且随着i增大,不断扩展个数
}
}
return row;
}
};
2.3 数学公式(线性递推)
思路
根据杨辉三角的性质可知, 每层的每个元素其实就是 \(C^m_n\)
对于组合数公式, 只要直到其中一个就可以地推出所有的项, 推导如下:
代码
class Solution {
public:
vector<int> getRow(int rowIndex) {
vector<int> row(rowIndex + 1);
row[0] = 1;
for(int i = 1; i <= rowIndex; i++){
row[i] = row[i-1] * (rowIndex - i + 1) / i;
}
return row;
}
};
``