先看一眼杨辉三角是啥
杨辉三角
题目1:
给定一个非负整数 numRows,生成杨辉三角的前 numRows 行。
示例:
输入: 5
输出:
[
[1],
[1,1],
[1,2,1],
[1,3,3,1],
[1,4,6,4,1]
]
class Solution {
//给定一个非负整数 numRows,生成杨辉三角的前 numRows 行。
public List<List<Integer>> generate(int numRows) {
List<List<Integer>> triangle = new ArrayList<List<Integer>>();
for(int i=1; i<=numRows; i++){ //循环行数
List<Integer> list_row = new ArrayList();
for(int j=1; j<=i; j++){ //每一行中循环列数(每一行的列数==行号)
if(j==1 || j==i){
list_row.add(1); //两侧补1
}else{
list_row.add(triangle.get(i-2).get(j-2) + triangle.get(i-2).get(j-1));
}
}
triangle.add(list_row);
}
return triangle;
}
}
题目2:
给定一个非负索引 k,其中 k ≤ 33,返回杨辉三角的第 k 行。
示例:
输入: 3
输出: [1,3,3,1]
进阶:
你可以优化你的算法到 O(k) 空间复杂度吗?
class Solution {
public List<Integer> getRow(int rowIndex) {
List<Integer> row_up_temp = new ArrayList();
for(int i=0; i<=rowIndex; i++){
List<Integer> row_cur = new ArrayList();
for(int j=0; j<=i; j++){
if(j==0 || j==i){
row_cur.add(1);
}else{
row_cur.add(row_up_temp.get(j-1) + row_up_temp.get(j));
}
}
row_up_temp = row_cur;
}
return row_up_temp;
}
}
另一种解法,公式法
根据组合数的公式,将(n-k)!约掉,化简就是下边的结果。
Cnk=n! / (k!(n−k)!)=(n∗(n−1)∗(n−2)∗...(n−k+1))/k!
public List<Integer> getRow(int rowIndex) {
List<Integer> ans = new ArrayList<>();
int N = rowIndex;
for (int k = 0; k <= N; k++) {
ans.add(Combination(N, k));
}
return ans;
}
private int Combination(int N, int k) {
long res = 1;
for (int i = 1; i <= k; i++)
res = res * (N - k + i) / i;
return (int) res;
}
我们可以优化一下。
上边的算法对于每个组合数我们都重新求了一遍,但事实上前后的组合数其实是有联系的。
Cnk=Cnk-1×(n−k+1)/k
代码的话,我们只需要用pre变量保存上一次的组合数结果。计算过程中,可能越界,所以用到了long。
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; k++) {
long cur = pre * (N - k + 1) / k;
ans.add((int) cur);
pre = cur;
}
return ans;
}
网友评论