认识杨辉三角形——用Python搭一个数字金字塔
中等3杨辉三角形——用Python搭出数字金字塔(详细教程)
同学们,你们玩过搭积木吗?一块积木放在下面,上面再放一块,每一层的积木都稳稳地坐在下面两块积木的中间。杨辉三角形就像一座数字搭成的金字塔,它也藏着一个简单又好玩的规律。这座金字塔不但形状漂亮,还藏着很多数学秘密——比如二项式系数、组合数,在概率、计算机科学里都有大用处。今天我们就一起动手,用Python把这座数字金字塔“搭”出来,顺便破解它的生成密码。
杨辉三角形的规律
杨辉三角形(也叫帕斯卡三角形)的每一行数字都有明确的生成规则:
- 第一行(第0行):只有一个数字
1。 - 第二行(第1行):两个
1。 - 从第三行开始,每一行的首尾都是
1,中间的数字等于它正上方和左上方两个数字 之和。
举一个具体的例子,看看第4行(索引从0开始)是怎么得来的:
第0行: 1
第1行: 1 1
第2行: 1 2 1
第3行: 1 3 3 1
第4行: 1 4 6 4 1
- 第4行(行号=4)有5个数字。
- 第1个数字(索引0):固定为1。
- 第2个数字(索引1):等于上面一行(第3行)的第0个和第1个数字之和:
1 + 3 = 4。 - 第3个数字(索引2):等于上面一行的第1个和第2个数字之和:
3 + 3 = 6。 - 第4个数字(索引3):等于上面一行的第2个和第3个数字之和:
3 + 1 = 4。 - 第5个数字(索引4):固定为1。
你发现没有?每一行的数字个数正好等于行号加一(第0行1个,第1行2个,……)。
用生活例子理解
想象你是一个小队长,要组建一个啦啦队。第一排只有队长自己(1)。第二排有两个队员(1,1)。第三排时,新队员站在两位老队员中间,他的位置就由左右两位老队员“合成”——如果左右都是1,新队员就是2。这样一排排站好,就排成了我们熟悉的杨辉三角形。
再比如,你每天有10元零花钱,想平均分给几个朋友。假设朋友人数是行号,那么每一行的数字就表示“分法”的种数——是不是很神奇?杨辉三角形里每一个数字都对应着 组合数 C(n, k),其中 n 是行号,k 是这一行第几个位置(从0开始)。例如第4行第2个数字是6,就表示从4个东西里选2个有6种选法。
用Python搭建杨辉三角形
我们可以用两层循环来生成这个三角形。第一层循环控制行数,第二层循环计算这一行中间的数字。最关键的是:上一行的数据我们保存在一个列表里,通过索引取出左、右邻居求和。
基本代码(保留原有逻辑并加详细注释)
def yanghui_triangle(n):
# 第一步:创建一个空的三角形列表,用来存放每一行
triangle = []
# 第二步:遍历每一行,行号从0到n-1
for row_num in range(n):
# 每一行先初始化一个全是1的列表,长度为行号+1
# 例如第0行有1个1,第1行有2个1……
row = [1] * (row_num + 1)
# 第三步:从第三行(row_num >= 2)开始,计算中间的数字
# 注意:第0行和第1行没有中间数字,所以循环从1到row_num-1
for j in range(1, row_num):
# 中间数字 = 上一行的左邻居 + 上一行的右邻居
# 左邻居:第row_num-1行的第j-1个
# 右邻居:第row_num-1行的第j个
row[j] = triangle[row_num - 1][j - 1] + triangle[row_num - 1][j]
# 把这一行添加到三角形列表中
triangle.append(row)
# 返回整个三角形(列表的列表)
return triangle
# 调用函数,打印5行杨辉三角形
n = 5
result = yanghui_triangle(n)
for line in result:
print(line)
运行后输出:
[1]
[1, 1]
[1, 2, 1]
[1, 3, 3, 1]
[1, 4, 6, 4, 1]
代码逐行解读(重点)
for row_num in range(n):— 从第0行到第4行(共5行)。row = [1] * (row_num + 1)— 比如row_num=2时,生成[1, 1, 1],但第二个1会被后面的循环覆盖成正确的数字。for j in range(1, row_num):— 注意range(1, row_num)当row_num=2时,range(1,2)只产生j=1;当row_num=1时,range(1,1)为空,循环不执行。row[j] = triangle[row_num - 1][j - 1] + triangle[row_num - 1][j]— 这里triangle[row_num-1]就是上一行列表,j-1和j就是左、右邻居的索引。
把三角形打印得更漂亮(对齐)
用列表输出默认是方括号、逗号。我们可以手动打印成真正的三角形形状,让每一行居中显示。下面这个函数会先计算最后一行的数字宽度,然后让每一行居中:
def print_triangle_pretty(tri):
# 获取最后一行的最后一个数字,转为字符串并计算长度,用来控制对齐
last_num = tri[-1][len(tri[-1]) // 2] # 取最后一行中间那个数
width = len(str(last_num)) * len(tri[-1]) # 估算宽度(粗略)
for line in tri:
# 把数字转成字符串并用空格连接
line_str = " ".join(str(num) for num in line)
# 居中打印,宽度等于估计宽度
print(line_str.center(width))
# 测试漂亮的打印
n = 6
triangle = yanghui_triangle(n)
print_triangle_pretty(triangle)
运行效果(n=6):
1
1 1
1 2 1
1 3 3 1
1 4 6 4 1
1 5 10 10 5 1
新手容易犯的错误
-
索引越界
在访问triangle[row_num - 1][j - 1]时,如果j=0或j=row_num,就会越界。所以循环只对j从1到row_num-1的中间位置操作,两端直接保留初始化的1。 -
忘记初始化行
有些同学先创建空列表row = [],然后通过append添加数字,但忘记在两端放1,导致中间数字计算后还要手动补1。用[1]*长度的方法更简单。 -
混淆行号和索引
row_num从0开始,但前面介绍规律时说“第一行”通常从1开始。在代码中要统一用0-based索引。比如第3行(行号3)有4个数字,中间位置j=1,2。 -
打印时数字挤在一起
直接用print(line)输出列表,数字之间没有空格,看起来不清晰。可以像上面那样用join转成字符串再打印。
完整可运行的示例(包含输入与格式化输出)
以下是一个完整的程序,让用户输入行数,然后打印漂亮的杨辉三角形:
def yanghui_triangle(n):
"""
生成n行的杨辉三角形
:param n: 行数(正整数)
:return: 二维列表,每个子列表是一行
"""
triangle = [] # 存放所有行的列表
for row_num in range(n):
# 当前行先全部初始化为1
row = [1] * (row_num + 1) # 行号0对应1个元素,行号1对应2个……
# 从第三行开始计算中间数字
for j in range(1, row_num):
# 中间数字 = 上一行左邻 + 上一行右邻
row[j] = triangle[row_num - 1][j - 1] + triangle[row_num - 1][j]
triangle.append(row)
return triangle
def print_triangle(tri):
"""
以三角形形状打印杨辉三角形(左对齐版,数字之间空格)
"""
for line in tri:
print(" ".join(str(num) for num in line))
def print_triangle_pretty(tri):
"""
以居中三角形形状打印(更美观)
"""
# 计算最后一行最宽的数值,用来确定缩进宽度
last_row = tri[-1]
max_width = len(" ".join(str(num) for num in last_row))
for line in tri:
line_str = " ".join(str(num) for num in line)
print(line_str.center(max_width))
# 用户输入行数
n = int(input("请输入杨辉三角形的行数:"))
triangle = yanghui_triangle(n)
print("\n普通打印:")
print_triangle(triangle)
print("\n漂亮打印:")
print_triangle_pretty(triangle)
运行示例(输入8):
请输入杨辉三角形的行数:8
普通打印:
1
1 1
1 2 1
1 3 3 1
1 4 6 4 1
1 5 10 10 5 1
1 6 15 20 15 6 1
1 7 21 35 35 21 7 1
漂亮打印:
1
1 1
1 2 1
1 3 3 1
1 4 6 4 1
1 5 10 10 5 1
1 6 15 20 15 6 1
1 7 21 35 35 21 7 1
杨辉三角形的秘密与延伸
你可能会问:学了搭杨辉三角形有什么用?其实它和 排列组合 关系密切。比如:
- 第n行第k个数等于组合数
C(n, k)(n和k从0开始)。例如第4行(n=4)第2个数字是6,就是C(4,2)=6。 - 二项式
(a+b)^n展开后的系数正好是杨辉三角形的第n行。例如(a+b)^3 = a^3 + 3a^2b + 3ab^2 + b^3,系数1,3,3,1就是第3行。
如果你想进一步探索,可以试试:
- 用递归函数生成杨辉三角形(另一种思路)。
- 用杨辉三角形计算组合数,并验证概率问题(比如抛硬币出现正面次数的可能情况)。
- 研究杨辉三角形的其他性质:每一行数字之和等于2的n次方;对角线上的数字是三角形数、四面体数……
掌握了用代码生成规律的能力,你就拥有了一把打开数学宝藏的钥匙。下次遇到类似的数字模式,都可以尝试用循环和列表去描述它。继续加油!
例题精讲
杨辉三角形中,第n行第k个数字(从0开始计数)的计算公式是什么?
在Python中打印杨辉三角形时,每一行的第一个和最后一个数字总是1。
以下Python代码用于生成杨辉三角形的前n行,请补全空缺。\ndef generate_pascal(n):\n triangle = []\n for i in range(n):\n row = [1] * (___)\n for j in range(1, i):\n row[j] = triangle[i-1][j-1] + triangle[i-1][j]\n triangle.append(row)\n return triangle在以下Python代码中,用于生成杨辉三角形第5行的正确循环范围是?\ndef pascal_row(n):\n row = [1]\n for k in range(1, n):\n next_val = row[-1] * (n - k) // k\n row.append(next_val)\n return row
以下代码用递归方式计算杨辉三角形中第n行第k个数字,请填空。\ndef pascal_recursive(n, k):\n if k == 0 or k == ___:\n return 1\n return pascal_recursive(n-1, k-1) + pascal_recursive(n-1, k)