给定一个非负索引 k
,其中 k ≤ 33
,返回杨辉三角的第 k 行。
在杨辉三角中,每个数是它左上方和右上方的数的和。
示例:
输入: 3
输出: [1,3,3,1]
进阶:
你可以优化你的算法到 O(k) 空间复杂度吗?
我的思路
迭代法
前面2行直接生成,第三行(nowIndex = 2)在上一个结果,即[1,1]
的倒数第二个位置插入2即可。
第4行及以后(nowIndex >= 3)的计算方法:都是在上一次结果的基础上进行修改。
- 第一个和最后一个元素保持不变,都是1。
- 第二个元素到倒数第三个元素,采用递推公式:
当前位置的新值 = 上一次结果前一个位置的值+上一次结果当前位置的值
,写成公式,就是res.get(j) = res.get(j - 1) + res.get(j);
。但是直接在程序上这样写是不行的,因为我是直接在原来的结果上进行修改。这样做,第一次没问题,第二次及以后,需要利用上一轮计算结果位置原来的值,由于上次的的结果res.get(j)
已经被修改了,因此计算结果就会出错。因此,需要设置2个变量second 和 first
来分别提前存储当前位置(j)和上一个位置的值(j-1),这样就没问题了。 - 倒数第2个元素采用插入法,需要用到
first
变量。
迭代法程序(Java)
class Solution {
public List<Integer> getRow(int rowIndex) {
List<Integer> res = new ArrayList<>();
res.add(1);
if(rowIndex == 0) return res; // 返回第一行[1]
res.add(1);
if(rowIndex == 1) return res; // 返回第二行[1,1]
for(int i = 2; i <= rowIndex; i++){
int j = 1;
int first = res.get(0), second = 0; // first 初始化为res的第一个值
// ***** 下面的 if 和 for 语句代码块的内容只有当 i >= 3 时才会执行
if(i >= 3){ // 当 i >= 3 时,才做下面的处理
j++;
first = res.get(1); // first 修改为res的第2个值
second = res.get(2); // first 修改为res的第3个值
res.set(1, res.get(0) + res.get(1));
}
for(; j < i - 1; j++){ // 只有当 i >= 3 才有可能进入for循环
res.set(j, first + res.get(j));
// first 用于计算,second用于提前保存下一个用于计算的值,避免因上一行的计算而被覆盖掉
first = second;
second = res.get(j + 1);
}
// ***** 当 i = 2 时,上面2个代码块不执行,只执行下面这个语句
res.add(j, first + res.get(j)); // 在最后一个数字 1 前面插入对应的数字
}
return res;
}
}
公式法
参考windliang的【解法二 公式法】,以及评论,我对原作者的程序做了一点修改,程序如下。测试了一下,其实原来的公式法程序还更快一点。
公式法程序(Java)
class Solution {
public List<Integer> getRow(int rowIndex) {
List<Integer> ans = new ArrayList<>();
int N = rowIndex;
long pre = 1;
ans.add(1);
for (int k = 1; k <= N/2; k++) { // 用公式只计算一半的内容
long cur = pre * (N - k + 1) / k;
ans.add((int) cur);
pre = cur;
}
for(int k = N/2 + 1; k <= N; k++){ // 剩下的内容,对称的位置复制过来即可
ans.add(ans.get(N - k));
}
return ans;
}
}
更多思路可参考:windliang
如有不当之处,欢迎读者批评指正!