LeetCode 118. 杨辉三角
题目描述



题意分析
输入只有一个整数
numRows,要求返回杨辉三角的前numRows行,输出是一个每行长度递增的二维列表。题面用图示定义了生成规则:每一行的两端固定是 1,中间的每个数等于它「肩上」的两个数之和,也就是上一行相邻两个位置相加。规则本身没有歧义,真正的难点全在下标上——第几行有几个元素、中间部分从哪开始到哪结束。
约束
1 <= numRows <= 30有两层含义:一是不存在numRows = 0的空输出,二是数值不会溢出(第 30 行的最大值约 7.7 亿,int装得下),不需要用long或大数。边界情况:
numRows = 1时只有一行[1];numRows = 2时第二行是[1,1],中间元素个数为 0,任何访问「上一行」的代码在这一行都不该被执行到。
解法:按定义逐行递推
核心思路
杨辉三角每一行只依赖上一行:两端固定为 1,中间位置满足
current[col] = previous[col - 1] + previous[col]题目要求返回前
numRows行,上一行本来就保存在答案中,因此直接按定义递推最简单;组合数公式会额外引入乘除顺序和溢出问题,没有必要。使用从 0 开始的行号后,第
row行长度为row + 1,合法下标是0..row。循环不变量是:构造第row行前,答案中已经完整保存前row行;因此中间位置引用的两个上一行下标一定存在。首尾单独赋 1 后,递推式逐项生成,数学归纳即可证明所有行正确。
解题步骤
- 从第 0 行依次构造到第
numRows - 1行。- 为第
row行创建长度为row + 1的容器。col == 0或col == row时填 1。- 其余位置填入上一行
col - 1与col两项之和。- 当前行完成后加入答案。
当
numRows = 5时,各行依次为[1]、[1,1]、[1,2,1]、[1,3,3,1]、[1,4,6,4,1]。第 0、1 行没有中间位置,主循环无需额外特判。
代码实现
import java.util.ArrayList;
import java.util.List;
class Solution {
public List<List<Integer>> generate(int numRows) {
List<List<Integer>> answer = new ArrayList<>(numRows);
for (int row = 0; row < numRows; row++) {
List<Integer> current = new ArrayList<>(row + 1);
for (int col = 0; col <= row; col++) {
if (col == 0 || col == row) {
current.add(1);
} else {
List<Integer> previous = answer.get(row - 1);
current.add(previous.get(col - 1) + previous.get(col));
}
}
answer.add(current);
}
return answer;
}
}
func generate(numRows int) [][]int {
answer := make([][]int, 0, numRows)
for row := 0; row < numRows; row++ {
current := make([]int, row+1)
current[0] = 1
current[row] = 1
for col := 1; col < row; col++ {
current[col] = answer[row-1][col-1] + answer[row-1][col]
}
answer = append(answer, current)
}
return answer
}
复杂度分析
- 时间复杂度:$O(n^2)$,其中 $n$ 是
numRows;共生成 $n(n+1)/2$ 个元素。- 空间复杂度:$O(n^2)$,用于返回全部元素;若不计返回值,额外空间为 $O(1)$。
关键点总结
- 递推式是题目定义的直接翻译,不需要组合数公式。
- 第
row行长度为row + 1,两端下标是 0 和row。- 只有
0 < col < row时才读取上一行,所以下标天然安全。- 面试追问只返回第
k行时,可用一维数组从右向左更新,将额外空间降为 $O(k)$。
易错点总结
- 内层循环写成
col < row,会漏掉每行最后一个 1。- 只设置左端点,右端位置按递推读取会访问上一行越界。
- 多行复用同一个可变列表,会让历史行被后续修改覆盖。
- 从当前行而非上一行读取,会使用尚未生成的数据。
- 一维原地优化若从左向右更新,会覆盖后面仍需使用的旧值。
相似题目
| 题目 | 难度 | 考察点 |
|---|---|---|
| 119. 杨辉三角 II | 简单 | 一维滚动数组倒序更新 |
| 509. 斐波那契数 | 简单 | 线性递推与滚动变量 |
| 70. 爬楼梯 | 简单 | 递推式的计数建模 |