python实现杨辉三角_Python算法之六:杨辉三角

关注微信公众号“酸痛鱼”,获得更多最新最全的文章。

本文中所涉及的代码,在未特殊声明的情况下,都是基于Python3程序设计语言编写的。

建议您在PC浏览器中阅读本文,以获得更好的阅读体验。

如果您未掌握知识提要中的内容,建议您先掌握这些内容之后再阅读本文。如果您看不懂本期的内容,建议您先阅读往期文章。

知识提要

1、range、lambda、reduce

2、二项式系数、组合数、杨辉三角

3、列表过滤语法

0

问题描述

杨辉三角,是二项式系数在三角形中的一种几何排列。给定一个非负索引n,返回杨辉三角的第n行。

例如:

输入:0

返回:[1]

输入:1

返回:[1, 1]

输入:2

返回:[1, 2, 1]

杨辉三解又叫Pascal’s Triangle,为了表述方便,在下文中,我们将用P(n)来代码杨辉三解的第n行。

1

问题分析

二项式系数,是二项(x+y)^n展开后各项的系数,第r列的值为C(n, r)。

杨辉三角是二项系数的几何排列,其相临两个行存在递推关系,如动图所示(图片来源于网络,若侵权,请通知删除),以及组合数的性质,我们可以推算出如下递推规律:

C(n, 0) = 1

C(n, n) = 1

C(n, r) = C(n - 1, r – 1) + C(n – 1, r) # n>1且r>0

所以,我们解决此题目的方式有两种,一种是公式法,一种是递推法。我们将首先介绍公式法,然后介绍递推法。本文的重点是介绍递推法,我们将一步步地简化递推法的空间复杂度。

2

公式法

根据二项式展开式的规律,我们知道:

P(n) = [C(n, 0), C(n, 1), …, C(n, n)]

所以我们只需要实现一个求组合数的函数即可以解决问题。

from functools import reduce

# 获取组合数C(n, m)

def combination(n, m):

if n <= m or m <= 0: return 1

if m > n / 2:

m = n - m

func = lambda a, b: a * b

val1 = reduce(func, range(m + 1, n + 1))

val2 = reduce(func, range(1, n - m + 1))

return val1 // val2

# 获取杨辉三角第n行

def GetTriangleRow(n):

return [combination(n, i) for i in range(n + 1)]

3

递推法

我们可以根据递推规律,构建杨辉三角,返回杨辉三角的最后一行即可。

# 获取杨辉三角第n行

def GetTriangleRow(n):

matrix = [[1] * (col + 1) for col in range(0, n + 1)]

for row in range(2, n + 1):

for col in range(1, row):

matrix[row][col] = matrix[row - 1][col - 1] + matrix[row - 1][col]

return matrix[n]

4

空间复杂度为O(n)的递推法

在第3节中,构建杨辉三角,需要存储大量额外临时空间matrix,matrix的元素数量为n(n+1)/2,所以空间复杂度为O(n^2)。

实际上,根据递推公式,我们只需要不停地存储P(n-1)和P(n)的结果即可,用此方法,空间复杂度可以降低为O(n)。虽然我们用到的空间是2n,但O(2n)也是O(n)。

def GetTriangleRow(n):

size = n + 1

result = [1] * size

for cols in range(3, size + 1):

cur_row = [1] * cols

for j in range(1, cols - 1):

cur_row[j] = result[j - 1] + result[j]

result = cur_row

return res

5

进一步减少递推法的空间复杂度

在第4节中,我们已经达到现了O(2n)的空间复杂度的效果。但如果我们非得实现真正意义上的O(n)也是可以做到的。

组合数公式有如下的规律:

C(n, r) = C(n, n – r)

根据这个规律,我们可以一开始便初始化P(n)的空间。在每一次迭代中,用P(i-1)的后一半的数值来推算出P(i)前一半的数值,并将P(i)前一半的结果存储在原来存储P(i-1)前一半数值的地方。最后用P(i)前一半得到P(i)后一半的结果。

由于P(i-1)中间项的值有可能会在推算P(i)的过程中被覆盖,所以我们需要首先单独推算并存储P(i)的中间一项。请关注代码中的mid_val变量。

def GetTriangleRow(n):

size = n + 1

result = [1] * size

for cols in range(2, size):

m = cols // 2

mid_val = result[m - 1] + result[m]

for j in range(1, m):

result[j] = result[cols - j] + result[cols - j - 1]

result[m] = mid_val

for j in range(m + 1, cols):

result[j] = result[cols - j]

return result● 扫码关注我嗄嘎嘎

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值