14.杨辉三角

本文介绍了一种生成杨辉三角的算法实现,通过迭代方法构建指定行数的杨辉三角,每一行的元素为其上一行对应位置两数之和。算法使用Java语言,通过ArrayList存储每行的数据。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题:给定一个非负整数 numRows,生成杨辉三角的前 numRows 行。

在杨辉三角中,每个数是它左上方和右上方的数的和。

示例:

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

代码:

public List<List<Integer>> generate(int numRows) {
     List<List<Integer>> list = new ArrayList<List<Integer>>();
        if (numRows <= 0) {
            return list;
        }
        
        for (int i = 1; i <= numRows; i++) {
            List li = new ArrayList();
            if (i == 1) {
                li.add(1);
                list.add(li);
                continue;
            }
            for (int j = 1; j <= i; j++) {
                if (j == 1) {
                    li.add(1);
                } else {
                    int a = list.get(i - 2).get(j - 2);
                    int b = list.get(i - 2).size() >= j ? list.get(i - 2).get(j - 1) : 0;
                    li.add(a + b);
                }
            }
            list.add(li);
        }
        return list;
    }
<think>我们正在分析LeetCode118题“杨辉三角”的多种解法,并分析每种解法的时间复杂度和空间复杂度(使用C++实现)。根据引用内容,我们已知:1.引用[1]指出时间复杂度为$O(numRows^2)$,空间复杂度为$O(n)$(但这里空间复杂度可能有误,因为杨辉三角需要存储整个二维数组,所以空间复杂度应该是$O(n^2)$)。2.引用[2][3][4]的代码实现都是使用二维数组,并明确时间和空间复杂度为$O(n^2)$(其中n是行数)。3.引用[5]是杨辉三角II(只返回第k行),但本题要求生成整个三角。题目要求:生成一个numRows行的杨辉三角杨辉三角的性质:-第i行(从0开始)有i+1个数。-每行的第一个和最后一个数都是1。-对于中间的元素,满足:triangle[i][j]=triangle[i-1][j-1]+triangle[i-1][j]我们将介绍三种常见解法,并分析复杂度:解法一:动态规划(二维数组法)——即用户提供的代码-描述:使用二维数组存储每一行,按照杨辉三角的递推关系填充。-时间复杂度:$O(n^2)$,因为需要填充$n$行,且第i行有$i$个元素(不包括首尾固定为1的元素,但整体操作次数为$\sum_{i=0}^{n-1}(i+1)=\frac{n(n+1)}{2}\inO(n^2)$。-空间复杂度:$O(n^2)$,因为存储了整个二维数组(杨辉三角的所有元素)。解法二:动态规划(一维数组滚动更新)——优化空间复杂度-描述:我们注意到,计算第i行时,只需要第i-1行的数据。因此,我们可以只维护一个一维数组(上一行),然后不断更新当前行,并将当前行保存到结果中。-但是,由于题目要求返回整个杨辉三角(所有行),所以我们必须存储每一行,因此空间复杂度无法优化到$O(n)$以下(至少需要$O(n^2)$存储结果)。所以这种方法在空间复杂度上并没有优化(结果空间是必须的)。-注意:如果题目像119题(杨辉三角II)一样只要求返回第k行,那么我们可以用$O(k)$的空间完成。但本题要求返回所有行,所以空间复杂度必然为$O(n^2)$。解法三:数学公式法(组合数)-描述:杨辉三角的第i行第j列(行列均从0开始)的值为组合数$C(i,j)$。因此,我们可以直接计算每个位置的值。-公式:$C(i,j)=\frac{i!}{j!\cdot(i-j)!}$,但是直接计算阶乘可能会导致溢出,而且计算阶乘的时间复杂度较高。-优化计算:我们可以用递推关系计算组合数:$C(i,j)=C(i,j-1)\times(i-j+1)/j$,这样避免阶乘。-时间复杂度:$O(n^2)$,因为要计算$n$行,每行最多$n$个元素,每个元素需要常数时间计算(递推关系)。-空间复杂度:$O(n^2)$(存储整个结果)。但是,解法三在实现时需要注意:-由于整数除法可能产生小数,但组合数一定是整数。因此,在递推计算中,我们可以保证整除(因为每一步都是整数乘法再除以整数,且能整除)。-然而,在C++中,整数除法在整除时是安全的,但要注意乘法可能溢出(使用`int`可能不够,但题目没有指定范围,通常numRows较小,如不超过30,则不会溢出)。然而,引用[2][3][4]都采用了二维数组的动态规划方法,这是最常见且易于理解的。因此,我们总结:-解法一(二维数组动态规划)是最直接的方法。-解法二(滚动数组)在本题中并不能降低空间复杂度(因为需要返回所有行),但在只要求输出一行时有效(如119题)。-解法三(组合数)在数学上直接,但实际实现可能不如动态规划简单,且可能有溢出问题。所以,在LeetCode118题中,通常采用解法一。现在,我们分析用户提供的代码(即解法一):-代码逻辑:vector<vector<int>>res(numRows);//创建有numRows行的二维vectorfor(inti=0;i<numRows;i++){res[i].resize(i+1,0);//每行调整大小为i+1,并初始化为0res[i][0]=res[i][i]=1;//首尾置1}for(inti=2;i<numRows;i++){//从第三行(下标2)开始for(intj=1;j<i;j++){res[i][j]=res[i-1][j-1]+res[i-1][j];//递推关系}}-时间复杂度:$O(n^2)$。外层循环执行了$n-2$次(从2到n-1),内层循环对于第i行执行了$i-1$次。所以总操作次数为$\sum_{i=2}^{n-1}(i-1)=\frac{(n-2)(n-1)}{2}\inO(n^2)$。另外,初始化部分循环了$n$行,每行初始化时间为$O(i)$(resize操作),初始化总时间也是$O(n^2)$。因此整体是$O(n^2)$。-空间复杂度:$O(n^2)$,因为存储了整个二维数组(结果),数组总元素数为$\frac{n(n+1)}{2}\inO(n^2)$。引用[1]中提到的空间复杂度为$O(n)$,这可能是错误的,因为结果需要$O(n^2)$空间。除非引用[1]只计算了额外辅助空间(但题目要求返回结果,结果空间通常计入空间复杂度),所以这里我们认为是$O(n^2)$。引用[4]明确指出时间和空间复杂度均为$O(n^2)$。因此,用户提供的代码的时间复杂度为$O(n^2)$,空间复杂度为$O(n^2)$。下面我们给出三种解法的C++代码示例(但注意解法二在本题中空间复杂度无法优化,所以我们只给出解法和分析,代码实现与解法一类似,因为必须存储每一行)。解法一:动态规划(二维数组)——用户代码,已给出解法二:动态规划(滚动数组,但用于生成每一行)——注意,由于需要保存每一行,所以空间复杂度不变,但可以节省中间计算时的额外空间(实际上解法一也不需要额外空间,因为直接使用上一行已经计算好的结果)。所以解法二的代码与解法一几乎一样,只是内层循环从后往前计算可以避免覆盖,但本题中我们不需要覆盖,因为要保存所有行。所以解法二在本题中不适用(或者没有优势)。解法三:组合数(递推计算)-代码示例:vector<vector<int>>generate(intnumRows){vector<vector<int>>res;for(inti=0;i<numRows;i++){vector<int>row(i+1);row[0]=1;//第一个元素为1//利用组合数递推关系:C(i,j)=C(i,j-1)*(i-j+1)/jfor(intj=1;j<=i;j++){//注意:这里用乘法递推,注意顺序和整数除法row[j]=(long)row[j-1]*(i-j+1)/j;}res.push_back(row);}returnres;}-注意:乘法可能会溢出,所以我们使用`long`转换。但题目中numRows一般不会太大(比如不超过30),所以不会溢出。-复杂度:同样$O(n^2)$时间和$O(n^2)$空间。总结:LeetCode118题主要有两种有效解法:动态规划(递推)和组合数法,时间和空间复杂度均为$O(n^2)$。相关问题:1.如果只需要返回杨辉三角的第k行(LeetCode119题),如何优化空间复杂度到$O(k)$?2.杨辉三角在组合数学中有哪些应用?例如,如何利用杨辉三角计算二项式展开的系数?3.杨辉三角与斐波那契数列之间有什么联系?</think>### LeetCode 118 杨辉三角:解法、时间与空间复杂度分析(C++) #### 一、题目要求 生成 `numRows` 行的杨辉三角,每个数是其左上方和右上方数的和。 示例: 输入:`numRows = 5` 输出: ``` [[1], [1,1], [1,2,1], [1,3,3,1], [1,4,6,4,1]] ``` --- #### 二、三种解法及复杂度分析 ##### 解法一:动态规划(二维数组)— **最优推荐** ```cpp class Solution { public: vector<vector<int>> generate(int numRows) { vector<vector<int>> res(numRows); for (int i = 0; i < numRows; i++) { res[i].resize(i + 1, 0); // 初始化当前行 res[i][0] = res[i][i] = 1; // 边界置1 for (int j = 1; j < i; j++) { // 填充中间元素 res[i][j] = res[i - 1][j - 1] + res[i - 1][j]; } } return res; } }; ``` - **时间复杂度**:$O(n^2)$ 需要填充 $\sum_{i=0}^{n-1} (i+1) = \frac{n(n+1)}{2}$ 个元素,属于平方级增长[^4]。 - **空间复杂度**:$O(n^2)$ 存储整个杨辉三角,元素总数 $\frac{n(n+1)}{2}$[^3]。 ##### 解法二:组合数公式(数学法) ```cpp class Solution { public: vector<vector<int>> generate(int numRows) { vector<vector<int>> res; for (int i = 0; i < numRows; i++) { vector<int> row; for (int j = 0; j <= i; j++) { row.push_back(combination(i, j)); // 计算组合数C(i,j) } res.push_back(row); } return res; } private: int combination(int n, int k) { long res = 1; // 避免乘法溢出 for (int i = 1; i <= k; i++) { res = res * (n - i + 1) / i; // 递推公式 } return (int)res; } }; ``` - **时间复杂度**:$O(n^3)$ 计算每个元素 $C(i,j)$ 需 $O(j)$ 时间,总操作数 $\sum_{i=0}^{n-1}\sum_{j=0}^{i} j = O(n^3)$。 - **空间复杂度**:$O(n^2)$(存储结果)。 ##### 解法三:递归(不推荐) ```cpp class Solution { public: vector<vector<int>> generate(int numRows) { if (numRows == 1) return {{1}}; vector<vector<int>> prev = generate(numRows - 1); vector<int> newRow(numRows, 1); for (int j = 1; j < numRows - 1; j++) { newRow[j] = prev.back()[j - 1] + prev.back()[j]; } prev.push_back(newRow); return prev; } }; ``` - **时间复杂度**:$O(n^2)$ 递归深度 $O(n)$,每层计算量 $O(n)$。 - **空间复杂度**:$O(n^2)$(存储结果 + 递归栈 $O(n)$)。 --- #### 三、复杂度对比总结 | 解法 | 时间复杂度 | 空间复杂度 | 适用场景 | |--------------|------------|------------|------------------| | 动态规划 | $O(n^2)$ | $O(n^2)$ | 最优解,代码简洁 | | 组合数公式 | $O(n^3)$ | $O(n^2)$ | 数学理论验证 | | 递归 | $O(n^2)$ | $O(n^2)$ | 教学演示 | > **推荐解法**:动态规划(解法一)是标准解法,时间/空间复杂度已达理论最优[^4]。 --- #### 四、杨辉三角的性质与应用 1. **性质**: - 第 $n$ 行第 $k$ 个元素为组合数 $C(n,k)$[^2]。 - 对称性:$C(n,k) = C(n, n-k)$。 2. **应用**: - 计算二项式展开系数:$(a+b)^n$ 的系数即第 $n$ 行[^2]。 - 概率论:二项分布的概率计算。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值