跳到主要内容

杨辉三角

介绍

杨辉三角,是二项式系数在三角形中的一种几何排列。它是中国古代数学的杰出研究成果之一,它把二项式系数图形化,把组合数内在的一些代数性质直观地从图形中体现出来,是一种离散型的数与形的结合。

杨辉三角性质:

  1. 每行数字左右对称,由 1 开始逐渐变大再变小,并最终回到 1。
  2. 第 n 行(从 0 开始编号)的数字有 n+1 项,前 n 行共有 n(n+1)/2 个数。
  3. 第 n 行的第 m 个数(从 0 开始编号) 可表示为可以被表示为组合数 C(n,m),记作 $C_n^m$ ,即为从 n 个不同元素中取 m 个元素的组合数。我们可以用公式来表示它:$C_n^m$ = $\frac{n!} {m!(n-m)!}$
  4. 每个数字等于上一行的左右两个数字之和,可用此性质写出整个杨辉三角。即第 n 行的第 i 个数等于第 n-1 行的第 i-1 个数和第 i 个数之和。这也是组合数的性质之一,即 $C_n^i$ = $C_n-1^i$ + $C_n-1^i-1$
  5. $(a+b)^{n}$ 的展开式(二项式展开)中的各项系数依次对应杨辉三角的第 n 行中的每一项

杨辉三角I

给定一个非负整数 numRows,生成「杨辉三角」的前 numRows 行。在「杨辉三角」中,每个数是它左上方和右上方的数的和。

示例1:

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

示例2:

输入: numRows = 1
输出: [[1]]

方案A 根据数学性质4

思路:依据性质 4,我们可以一行一行地计算杨辉三角。每当我们计算出第 i 行的值,我们就可以在线性时间复杂度内计算出第 i+1 行的值。

:::details 点击查看代码

function pascalsTriangle(numRows){
const result=[];
for(let i=0;i<numRows;i++){
const row=new Array(i+1).fill(1);
for(let j=1;j<row.length-1;j++){
row[j]=result[i-1][j-1]+result[i-1][j];
}
result.push(row);
}
return result
}

console.log(pascalsTriangle(4));

:::

性能分析:

时间复杂度:O(numRows2)。

空间复杂度:O(1)

杨辉三角II

给定一个非负索引 rowIndex,返回「杨辉三角」的第 rowIndex 行。

示例1:

输入: rowIndex = 3
输出: [1,3,3,1]

示例2:

输入: rowIndex = 0
输出: [1]

示例3:

输入: rowIndex = 1
输出: [1,1]

方案A 根据性质4递推

思路:根据性质 4 公式 $C_n^i$ = $C_n-1^i$ + $C_n-1^i-1$ ,当前行第 i 项的计算只与上一行第 i-1 项及第 ii 项有关。因此我们可以倒着计算当前行,这样计算到第 i 项时,第 i-1 项仍然是上一行的值。

function pascalsTriangleRow(rowIndex){
const row=new Array(rowIndex+1).fill(0);
row[0]=1;
for(let i=1;i<=rowIndex;i++){
for(let j=i;j>0;j--){
row[j]+=row[j-1]
}
}
return row
}

console.log(pascalsTriangleRow(4));

性能分析:

时间复杂度:O(rowIndex^2)

空间复杂度:O(1)。

方案B 根据性质3递推

思路: 由组合公式 $C_n^m$ = $\frac{n!} {m!(n-m)!}$ 可以得到同一行的相邻组合数的关系 $C_n^m$ = $C_n^m-1$ * $\frac{n-m+1} {m}$ 由于 $C_n^m$ = 1 ,利用上述公式我们可以在线性时间计算出第 n 行的所有组合数。

function pascalsTriangleRow(rowIndex){
const row=new Array(rowIndex+1).fill(0);
row[0]=1;
for(let i=1;i<=rowIndex;i++){
row[i]=row[i-1]*(rowIndex-i+1)/i;
}
return row
}

console.log(pascalsTriangleRow(4));