题目描述:
给定一个非负索引 rowIndex
,返回「杨辉三角」的第 rowIndex
行。
在「杨辉三角」中,每个数是它左上方和右上方的数的和。
方法一:
class Solution {
public:
vector<int> getRow(int rowIndex) {
vector<vector<int>> yang(rowIndex+1);
for(int i=1 ; i<=rowIndex+1 ; i++)
{
for(int j=0 ; j<i ; j++)
{
if(j==0 || j==i-1)
{
yang[i-1].push_back(1);
}
else
{
int x = yang[i-2][j-1] + yang[i-2][j];
yang[i-1].push_back(x);
}
}
}
return yang[rowIndex];
}
};
直接利用上一题的代码求出前rowIndex行的杨辉三角,然后再返回第rowIndex行
方法一的优化:
class Solution {
public:
vector<int> getRow(int rowIndex) {
vector<int> yang , ano;
for(int i=1 ; i<=rowIndex+1 ; i++)
{
ano.resize(i);
for(int j=0 ; j<i ; j++)
{
if(j==0 || j==i-1)
{
ano[j] = 1;
}
else
{
int x = yang[j-1] + yang[j];
ano[j] = x;
}
}
yang = ano;
}
return yang;
}
};
注意到,方法一中实际上每次遍历只用到了数组前一行的内容,所以利用滚动数组的思想,只用yang和ano两个数组,大大减少了空间复杂度(但不知为何运行时间也减少了)
方法一的进一步改进:
class Solution {
public:
vector<int> getRow(int rowIndex) {
vector<int> yang(rowIndex+1);
yang[0] = 1; //无论哪一行,该行的首位数字永远为1,不用改变
for(int i=1 ; i<=rowIndex ; i++)
{
for(int j=i ; j>0 ; j--)
{
yang[j] = yang[j] + yang[j-1];
}
}
return yang;
}
};
针对上一种改进方法的进一步改进,只用一个数组来写,使空间复杂度又进一步减少。这种方法的运行举例如下图所示:
当遍历到i等于3时,此时yang数组中存放的数据为杨辉三角的第2行1,2,1,从后往前计算,yang[j] = yang[j] + yang[j-1]即能表示第3行中的第j个数据为第2行的第j个数据和第j-1个数据之和。由于每一行的首数字永远都为1,所以在遍历计算的过程中不用考虑到yang[0]。
时间复杂度:O(rowIndex²)。
空间复杂度:O(1)。
方法二(线性递推法):
class Solution {
public:
vector<int> getRow(int rowIndex) {
vector<int> yang(rowIndex+1);
yang[0] = 1;
for(int i=1 ; i<=rowIndex ; i++)
{
yang[i] = 1LL * yang[i-1] * (rowIndex-i+1)/i;
}
return yang;
}
};
根据题解:
其中的1LL:LL代表long long
, 计算时*1LL
是为了把int类型的变量转化为long long,
防止溢出(没想通为啥这里会溢出)
时间复杂度:O(rowIndex)。
空间复杂度:O(1)