杨辉三角
介绍
杨辉三角,是二项式系数在三角形中的一种几何排列。它是中国古代数学的杰出研究成果之一,它把二项式系数图形化,把组合数内在的一些代数性质直观地从图形中体现出来,是一种离散型的数与形的结合。
杨辉三角性质:
- 每行数字左右对称,由 1 开始逐渐变大再变小,并最终回到 1。
- 第 n 行(从 0 开始编号)的数字有 n+1 项,前 n 行共有 n(n+1)/2 个数。
- 第 n 行的第 m 个数(从 0 开始编号) 可表示为可以被表示为组合数 C(n,m),记作
$C_n^m$
,即为从 n 个不同元素中取 m 个元素的组合数。我们可以用公式来表示它:$C_n^m$ = $\frac{n!} {m!(n-m)!}$
- 每个数字等于上一行的左右两个数字之和,可用此性质写出整个杨辉三角。即第 n 行的第 i 个数等于第 n-1 行的第 i-1 个数和第 i 个数之和。这也是组合数的性质之一,即
$C_n^i$ = $C_n-1^i$ + $C_n-1^i-1$
$(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));