118. 杨辉三角(Pascal’s Triangle)

难度:简单 | 主题:DP、数组

题目

给定 numRows,生成杨辉三角的前 numRows 行。

示例:

 
输入:numRows = 5
 
输出:[[1],[1,1],[1,2,1],[1,3,3,1],[1,4,6,4,1]]
 

思路

先讲个故事:叠罗汉

学校运动会上,班里要排一个人体金字塔:最顶层 1 个人,第二层 2 个人,第三层 3 个人……每一层的人站在下面两个人的肩膀上

  • 最左边的人只被一个人撑着(最右边也是)——所以他们只管自己站着

  • 中间的人被两个人撑着——他的重量 = 下面左肩 + 下面右肩

杨辉三角就是这种”叠罗汉”的数字版本:每个数等于它左上方和右上方两个数之和


引导式推导:从手动搭金字塔到找公式

第 0 行(n=0):塔尖——就 1 个人 → [1]

第 1 行(n=1):两个人,每人站一边 → [1, 1]

第 2 行(n=2):三个人——中间的人站在下面两个人(1 和 1)肩膀上 → [1, 2, 1]

第 3 行(n=3):四个人——中间两个,左边 1+2=3,右边 2+1=3 → [1, 3, 3, 1]

第 4 行(n=4):五个人——中间三个,3+3=6 → [1, 4, 6, 4, 1]

 
      [1]           ← 第 0 行
 
     [1, 1]         ← 第 1 行
 
    [1, 2, 1]       ← 第 2 行     2 = 1+1
 
   [1, 3, 3, 1]     ← 第 3 行     3 = 1+2, 3 = 2+1
 
  [1, 4, 6, 4, 1]   ← 第 4 行     6 = 3+3
 

发现规律:第 i 行第 j 个数 = 第 i-1 行第 j-1 个数 + 第 i-1 行第 j 个数

 
dp[i][j] = dp[i-1][j-1] + dp[i-1][j]
 

而且首尾永远是 1(只有一个肩膀的人撑着)。


四层递进:从建表到直接算


graph LR

    subgraph 四层递进

        A["暴力组合数<br/>O(n²) 大数阶乘"]

        B["DP 二维表<br/>O(n²) O(n²)"]

        C["滚动数组<br/>O(n²) O(n)"]

        D["组合公式<br/>O(n) O(1)"]

    end

    A -->|递推避免重复计算| B

    B -->|每行只依赖上一行| C

    C -->|发现数学本质| D

暴力组合数:第 n 行第 k 个数 = C(n,k) = n! / (k!×(n-k)!)。但算阶乘容易溢出,而且每次重新算——做了大量重复工作。

DP 二维表:每一行基于上一行计算,dp[i][j] = dp[i-1][j-1] + dp[i-1][j]。每个数只加一次。

滚动数组:发现 dp[i] 只依赖 dp[i-1],只需要保存上一行。空间从 O(n²) 降到 O(n)。

组合公式一横行输出:如果只需要第 n 行(119 题),递推公式 C(n,k) = C(n,k-1) × (n-k+1) / k,O(n) 时间 O(1) 空间。


代码

 
def generate(self, numRows):
 
    res = []                                   # 存储所有行(二维列表)
 
    for i in range(numRows):                   # 逐行生成:i 从 0 到 numRows-1
 
        row = [1] * (i + 1)                    # 初始化当前行:长度 = i+1,全部填充为 1(首尾自然为 1)
 
        for j in range(1, i):                  # 填充中间元素:j 从 1 到 i-1(跳过首尾的 1)
 
            row[j] = res[i-1][j-1] + res[i-1][j]  # 上一行相邻两数之和:左上方 + 右上方
 
        res.append(row)                        # 当前行加入结果列表
 
    return res
 

复杂度

指标解释
时间O(n²)每行 j 循环次数递增,总和 = 1+2+…+n = n(n-1)/2
空间O(n²)存储所有行的结果
滚动数组O(n)只保留上一行,适合只求第 n 行(119题)

实战考量

频率分析

出现在:字节/阿里/腾讯 DP 入门题,约 20% 的 AI Agent 常会从杨辉三角开始热身。不是考你算法多难,而是看你能不能写出整洁的递推循环

延伸思考

Q:row = [1] * (i + 1) 为什么首尾不需要单独处理?

A:列表初始化为全 1,首尾自动就是 1。中间元素后续会被覆盖。这种写法比手动设首尾 1 再填充中间更简洁。

Q:如果只要求返回第 n 行(119 杨辉三角 II),怎么优化?

A:滚动数组 + 从后往前更新row[j] = row[j] + row[j-1],从右往左算避免覆盖。空间 O(n)。

Q:杨辉三角第 n 行第 k 个数有数学公式吗?

A:组合数 C(n,k)。可以用递推 C(n,k) = C(n,k-1) × (n-k+1) / k 避免大数阶乘。进阶亮点。

Q:杨辉三角有哪些数学性质?

A:每行对称(C(n,k) = C(n,n-k));每行和 = 2ⁿ;斜对角线和 = 斐波那契数列;第 n 行中间的数最大(二项式系数最大)。

Q:杨辉三角在组合数学里有什么用?

A:(a+b)ⁿ 展开的系数就是杨辉三角第 n 行。比如 (a+b)³ = a³ + 3a²b + 3ab² + b³,系数正是 [1,3,3,1]

易错点

  • row = [1] * (i + 1) 是全 1 初始化,不是 [1]

  • j 范围是 range(1, i)(去掉首尾),不是 range(0, i+1)

  • res[i-1] 有 i>=1 的前提条件


生活类比

杨辉三角 → 叠罗汉 → 组合数

杨辉三角就像叠罗汉:最顶层 1 个人,每个人站在下面两个人的肩膀上。中间的受力 = 左肩 + 右肩。站在第 n 排第 k 个位置的人,头顶上有 C(n,k) 条”人链”通向塔尖——这就是组合数的物理意义。每一行就是对 (a+b)ⁿ 展开后各类项的”人数统计”。


相关题目

题目关系
300最长递增子序列同为一维 DP,状态转移思路可类比
120三角形最小路径和三角形 DP,自底向上递推
70爬楼梯DP 入门,斐波那契递推
118杨辉三角本题,DP 数组基础

→ 返回题单:LeetCode学习路线图 > 十三、动态规划

速记卡(面试闪卡)

Q1:一句话讲清「118. 杨辉三角(Pascal’s Triangle)」到底是什么?

A:生成杨辉三角前 numRows 行,每个数等于它左上方和右上方两数之和,首尾恒为 1。

Q2:叠罗汉与组合数(Pascal’s Triangle) —— 怎么理解?

A:类比:像叠罗汉——最顶层 1 个人,每人站在下面两人的肩膀上,中间受力 = 左肩 + 右肩。站在第 n 排第 k 个的人,头顶有 C(n,k) 条人链通向塔尖,这正是组合数,也是 (a+b)ⁿ 展开的系数。(Combination)

Q3:递推公式(dp transition) —— 怎么理解?

A:类比:状态转移 dp[i][j] = dp[i-1][j-1] + dp[i-1][j],首尾永远是 1。代码里 row=[1]*(i+1) 全 1 初始化,中间元素再覆盖,比手动设首尾更简洁——初始化即把肩膀位先铺好。(dp[i][j] = up-left + up-right)

Q4:优化与 119 题(rolling array) —— 怎么理解?

A:类比:发现 dp[i] 只依赖上一行,可用滚动数组把空间从 O(n²) 降到 O(n);若只求第 n 行(119 题),用组合数递推 C(n,k)=C(n,k-1)×(n-k+1)/k,做到 O(n) 时间 O(1) 空间。(Space O(n))

Q5:复杂度与数学性质(O(n²) time) —— 怎么理解?

A:类比:时间 O(n²)、空间 O(n²)(滚动 O(n))。数学亮点:每行对称、每行和 = 2ⁿ、斜对角线和 = 斐波那契数列、中间数最大。(Symmetry & 2ⁿ)

Q6:核心速记主线有哪些?

  • 题目:生成前 numRows 行,肩上两数相加

  • 思路:dp[i][j] = 左上 + 右上,首尾恒 1

  • 优化:滚动数组降空间,119 题用组合数

  • 性质:对称、行和 2ⁿ、斜线和 = 斐波那契

  • 复杂度:时间 O(n²)、空间 O(n²)/O(n)

口诀

A:杨辉三角叠罗汉,

肩上两数相加算;

首尾恒一是 1,

组合数里见真章。

相关链接