python程序打印出10行的杨辉三角_Python-零基础自学系列之求素数、杨辉三角

243702d5e8d508ab28f78c8e556c0b9f.png

求100内的素数

为了比较算法效率我们扩大到求100000内素数

# 1 简单算法

  • #一个数能被从2开始到自己的平方根的正整数整数整除,就是合数
import 

# 2 使用奇数

import 

# 3 存储质数

  • #合数一定可以分解为几个质数的乘积, 2 是质数
  • #质数一定不能整除1和本身之内的整数
import 

# 4 在#3的基础上缩小范围

import 

算法2和算法4对比,算法2的奇数应该是多余算法4的,也就是算法4应该要快一点,但是测试的计时却不是,为什么?

结果是增加了质数列表反而慢了,为什么?

修改算法如下

# 4 缩小范围

这回测试,速递第一了。也就是增加了列表,记录了质数,控制了边界后,使用质数来取模比使用奇数计算更少。

空间换时间,使用列表空间存储质数列表,来换取计算时间。

孪生素数性质

大于3的素数只有6N-1和6N+1两种形式,如果6N-1和6N+1都是素数称为孪生素数

import 

用了这个性质并没有超过算法4,原因还是在于使用列表存储已经计算得到的素数来减少计算。请自行使用列表完成素数的存储。

计算杨辉三角前6行

7c7bb55a5fef2a9f07dcd027382ce965.png

n行有n项,n是正整数

第n行数字之和为2**(n-1)

dacdc4ce1fae4ad3f1a4a8e59c50061c.png

解法1 杨辉三角的基本实现

下一行依赖上一行所有元素,是上一行所有元素的两两相加的和,再在两头各加1

607185c7afe5a34e36ce7247a254f45e.png

预先构建前两行,从而推导出后面的所有行

triangle 

变体

从第一行开始

triangle 

解法2 补零

  • 除了第一行以外,每一行每一个元素(包括两头的1)都是由上一行的元素相加得到。如何得到两头的1呢?
  • 目标是打印指定的行,所以算出一行就打印一行,不需要用一个大空间存储所有已经算出的行。

607185c7afe5a34e36ce7247a254f45e.png

for循环实现

n 

解法3 对称性

思路:

  • 能不能一次性开辟空间,可以使用列表解析式或者循环迭代的方式。
  • 能不能减少一半的数字计算。左右对称。

c088632855c7316d7f8fc48696698f49.png

1、 构建行

triangle 

上面创建每一行的代码过于啰嗦了,一次性创建出一行,以后覆盖其中数据就行了

triangle 

2、 中点的确定

[1]
[1, 1]
[1, 2, 1]
[1, 3, 3, 1]
[1, 4, 6, 4, 1]
[1, 5, 10, 10, 5, 1]
把整个杨辉三角看成左对齐的二维矩阵。
i==2时,在第3行,中点的列索引j==1
i==3时,在第4行,无中点
i==4时,在第5行,中点的列索引j==2
得到以下规律,如果有i==2j,则有中点
triangle 

上面的代码row[-j-1] = val 多做了一次

triangle 

另一种中点的处理

                                i   中点索引   j
[1]
[1, 1]
[1, 2, 1]                       2   1 or -2    0
[1, 3, 3, 1]
[1, 4, 6, 4, 1]                 4   2 or -3    1
[1, 5, 10, 10, 5, 1]
[1, 6, 15, 20, 15, 6, 1]        6   3 or -4    2

由此,得到中点的索引处i和j关系为i=2*(j+1)

其实,相当于上例中代码的j循环向左平移1,将所有的j变成 j+1

# 对称

解法4 单行覆盖

  • 方法2每次都要清除列表,有点浪费时间。
  • 能够用上方法3的对称性的同时,只开辟1个列表实现吗?

c088632855c7316d7f8fc48696698f49.png

首先我们明确的知道所求最大行的元素个数,例如前6行的最大行元素个数为6个。

下一行等于首元素不变,覆盖中间元素。

n = 6
row = [1] * n # 一次性开辟足够的空间
print(row)
print('-' * 30)

for i in range(n):
    print(row[:i+1])

运行结果如下
[1, 1, 1, 1, 1, 1]
------------------------------
[1]
[1, 1]
[1, 1, 1]
[1, 1, 1, 1]
[1, 1, 1, 1, 1]
[1, 1, 1, 1, 1, 1]

由于,这一次直接开辟了所有大小的列表空间,导致负索引比较难计算。

是否可以考虑直接使用正索引计算呢?

263fb3c1964c618d367e844e19f1c4de.png

以第七行为例,索引1对称索引为5,而1 + 5 = 6当前索引值。

n 

问题出在哪里了呢?

原因在于,4覆盖了3,导致3+3变成了3+4才有了7。使用一个临时变量解决

n 

也可以写成下面这样

n 

持续更新中......

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值