题目描述
给定一个非负整数 numRows,生成杨辉三角的前 numRows 行。
在杨辉三角中,每个数是它左上方和右上方的数的和。
示例 :
输入: 5
输出:
[
[1],
[1,1],
[1,2,1],
[1,3,3,1],
[1,4,6,4,1]
]
分析与代码
-
杨辉三角的五条性质
- 第 n 行的数字个数为 n。
- 左右数字对称,从 1 开始到 1 结束。
- 第 n 行的第 k 个数字为 (C_{n-1}^{k-1}) 。
- 第 n 行数字之和为 (2^{n-1})。
- 除了每行的第一个数字和最后一个数字,第 n 行的第 k 个数字等于第 n - 1 行的第 k - 1 个数字与第 n - 1 行的第 k 个数字之和。
-
创建 triangle 集合作为返回值,保存每行结果。
List<List<Integer>> triangle = new ArrayList<>();
解法一:迭代
- 先处理第一行,如果 numRows 为 0,直接返回空的 triangle,否则加入第一行。
- 从第二行起,每行第一个和最后一个都是 1,中间数字则由前一行的求出。
- 返回 triangle。
代码:
class Solution {
public List<List<Integer>> generate(int numRows) {
List<List<Integer>> triangle = new ArrayList<>();
if (numRows == 0) {
return triangle;
}
triangle.add(new ArrayList<Integer>(1));
triangle.get(0).add(1);
for (int i = 1; i < numRows; i++) {
List<Integer> row = new ArrayList<>(i + 1);
row.add(1);
for (int j = 1; j < i; j++) {
row.add(triangle.get(i - 1).get(j - 1) + triangle.get(i - 1).get(j));
}
row.add(1);
triangle.add(row);
}
return triangle;
}
}
解法二:递归
- 其实就是把循环的部分写成递归函数,每次调用
generate(numRows - 1)
,直到回到第一层,然后再往下生成。 - 递归终止条件就是回到第一行,或 numRows == 0。
代码:
class Solution {
public List<List<Integer>> generate(int numRows) {
List<List<Integer>> triangle = new ArrayList<>();
if (numRows == 0) {
return triangle;
}
if (numRows == 1) {
triangle.add(new ArrayList<Integer>(1));
triangle.get(0).add(1);
return triangle;
}
triangle = generate(numRows - 1);
List<Integer> row = new ArrayList<>(triangle.size() + 1);
row.add(1);
for (int j = 1; j < triangle.size(); j++) {
row.add(triangle.get(triangle.size() - 1).get(j - 1) + triangle.get(triangle.size() - 1).get(j));
}
row.add(1);
triangle.add(row);
return triangle;
}
}
小结
迭代法可以归类为动态规划,用前一行构造每一行。