跑溜Python杨辉三角的解法,玩转Python列表,脱离编程小白-Wayne 5

杨辉三角Python解法1.0

杨辉三角Python解法1.1

Python杨辉三角打印最朴素解法:把前两项作为特殊项,这个算法可以集中练习索引的边界问题。

>>> n = 6
>>> triangle = [[1],[1,1]]
# 这里留白分段,好的书写习惯让编码便于阅读
>>> for i in range(2,n):
>>>     cur = [1]
>>>     pre = triangle[i-1]
>>>     triangle.append(cur)  
>>>     for j in range(i-1):        
>>>         cur.append(pre[j]+pre[j+1])
>>>     cur.append(1)
#     triangle.append(cur)    
["{}".format(i) for i in triangle]

杨辉三角Python打印解法1.2

解法1的升级完善版本,所有项目自动生成。

>>> n = 6
>>> triangle = []  # 容器里面放各个行
# 这里留白分段,好的书写习惯让编码便于阅读
>>> for i in range(n):
>>>     cur = [1]
>>>     triangle.append(cur) # 引用数据类型cur,先append后修改和先修改后append效果一样
>>>     pre = triangle[i-1]
>>>     if i ==0:
>>>         continue               # continue的用法!
>>>     for j in range(i-1):
        
>>>         cur.append(pre[j]+pre[j+1])
>>>     cur.append(1)
#     print(cur)
#     triangle.append(cur)   引用数据类型cur,先append后修改和先修改后append效果一样
>>> ["{}".format(i) for i in triangle]

Python杨辉三角打印解法1.3

如上两个版本必须要生成第1-n行,降低空间复杂度。解法3只用2行循环,便实现第n行的生成。
这个方法好吗?

  • 优点:从解法1-2的多行到现在的双行,降低了空间复杂度;
  • 缺点:内存在大量丢弃计算出来的数据,而大量丢弃计算出来的数据的编程方法,一般是需要反思的。
>>> n = 6
# >>> triangle = []  # 不用这个容器了,存储所有了,注释不用。
>>> pre = []
>>> cur = []
# 这里留白分段,好的书写习惯让编码便于阅读
>>> for i in range(n):
>>>     cur = [1]
>>>     if i == 0:
#         print(cur)
>>>         pre = cur
>>>         continue  # continue的用法!
>>> 
>>>     for j in range(i - 1):
>>>         cur.append(pre[j] + pre[j + 1])
>>>     cur.append(1)
>>>     pre = cur   # 新pre产生,旧pre引用计数清零;在适当的时机,内存清理它。

>>> print(["{}".format(i) for i in cur])
['1', '5', '10', '10', '5', '1']
# 解法3的近似体
>>> n = 6
# >>> triangle = []  # 不用这个容器了,存储所有了,注释不用。
>>> pre = [1]

>>> # 这里留白分段,便于阅读
>>> for i in range(n):
>>>     cur = [1]
>>>     if i == 0:
>>>         # print("cur",cur)
>>>         continue  # continue的用法!
>>>     if i == 1:
>>>         cur.append(pre[i-1])
>>>         # print("i=1 cur", cur)
>>>     for j in range(i - 1):
        cur.append(pre[j] + pre[j + 1])
>>>     cur.append(1)
>>>     pre = cur
    # print("pre", pre)
>>> print(["{}".format(i) for i in cur])
['1', '5', '10', '10', '5', '1']

Python杨辉三角打印解法1.4

在3基础上做优化,将语句进行润色;效率上与Python杨辉三角打印解法3是一样的没有区别:

>>> n = 6
>>> pre = []

# 这里留白分段,好的书写习惯让编码便于阅读
>>> for i in range(n):
>>>     cur = [1]
>>>     if i != 0:  # 把啰嗦的if =0 ,换成语句更通顺的逻辑。
>>>         for j in range(i - 1):
>>>             cur.append(pre[j] + pre[j + 1])
>>>         cur.append(1)
>>>     pre = cur    

>>> print(["{}".format(i) for i in cur])
['1', '5', '10', '10', '5', '1']

Python杨辉三角打印解法1.5

用一次开辟列表index的方法

>>> n = 6  # 我们从n=1开始演算
>>> for i in range(n):
>>>     cur = [1]*(i+1)  #我们这次不再赋值None,而是赋值1,这样就省得再修改首尾的1了 
    
>>>     for j in range( i - 1):  #j=2```3
>>>         cur[j+1]=pre[j+1]+pre[j]  # 这里因为cur的下标变成了j+1,所以pre的小标对应的也要各增加1
>>>     print("cur in this loop ",cur)
>>>     pre = cur    

>>> print(["{}".format(i) for i in cur])
cur in this loop  [1]
cur in this loop  [1, 1]
cur in this loop  [1, 2, 1]
cur in this loop  [1, 3, 3, 1]
cur in this loop  [1, 4, 6, 4, 1]
cur in this loop  [1, 5, 10, 10, 5, 1]
['1', '5', '10', '10', '5', '1']

2.0 杨辉三角的Python算法(补0法):

2.1 杨辉三角的Python补0法,append法

通过观察,如果在前面一行的两端补0,后面一行。
编码中规避了在index[0]的位置补0,有利于规避线性数据结构的效率损失

>>> n = 6
>>> pre = [1]
>>> for i in range(1,n):
>>>     cur = []
>>>     pre.append(0)
>>>     
>>>     for j in range(i+1):
>>>         cur.append(pre[j-1]+pre[j+0])  # 这里使用了负索引的技巧!
>>> #     print("this cur",cur)
>>>     pre = cur
>>> print(cur)
[1, 5, 10, 10, 5, 1]

2.2 杨辉三角的Python补0算法

一般来说,一次性开辟内存空间。一般来说,频繁的append效率没有一次性扩展一定大小好。
如上“2.1 杨辉三角的Python补0法”中,append的方法要每次追加,那效率就不如一次性生成效率高;本部分升级将cur使用 cur= [None]*(i+1)一次性开辟所有列表元素,从而提高了Python代码的效率。
这是一种Python编程提高效率的技巧,对于列表来说,如果知道未来列表有多大,而且你即将逐个将其占满的话,不如直接一次性开辟好这么大的空间。虽然Python append实际上因为做了优化,所以当使用append追加时候,Python在最后的元素之后已经预留了一定空间,所以这个技巧实操起来可能并不一定可以感受到效率提高,但这是一种很好的编程思想和习惯。
当然,如果你并无法知道未来将用多大的列表,那就只能用append了。

>>> n = 6 
>>> pre = [1]

>>> for i in range(1, n): 
>>>     pre.append(0)  # 补0:这里注意无需补2个0;并且规避在index[0]的补零有利于提高效率 # pre =[1,0]```pre=[1,1,0]```pre=[1,2,1,0]
>>>     cur = [None]*(i+1) 
>>>     print("----")
>>>     for j in range(i+1):
>>>         cur[j]=pre[j-1]+pre[j]
            
>>>     pre = cur    #[1,2,1]
>>>     print("cur in this loop",cur)

>>> print(["{}".format(i) for i in cur])
----
cur in this loop [1, 1]
----
cur in this loop [1, 2, 1]
----
cur in this loop [1, 3, 3, 1]
----
cur in this loop [1, 4, 6, 4, 1]
----
cur in this loop [1, 5, 10, 10, 5, 1]
['1', '5', '10', '10', '5', '1']

3.0 杨辉三角的Python算法:对称算法

3.1 杨辉三角的Python算法:对称算法

对称算法通过使用列表的对称,将计算量缩减了一般。
同时,我们使用1.0的方法,将所有行都不视为特例。
且不使用2.0的补0法(因为补0法是一个很好的列表练习,但效率并不高),但将其中的一次性开辟列表空间的思想应用。
>>> n = 6  # 我们从n=1开始演算
>>> for i in range(n):
>>>     cur = [1]*(i+1)  #我们这次不再赋值None,而是赋值1,这样就省得再修改首尾的1了 
    
>>>     for j in range( i//2):  #这里要找计算几次的规律: 1--0;2--1;3--1;4--2;5--2
>>>         cur[j+1] = pre[j+1]+pre[j]
>>>         cur[-(j+1)-1]= cur[j+1]  #列表的对称位索引,值得记忆!!!
        #### 等于 cur[-j-2] = cur[j+1]
>>>     print("cur in this loop ",cur)
>>>     pre = cur    

>>> print("对称算法3.1",["{}".format(i) for i in cur])
cur in this loop  [1]
cur in this loop  [1, 1]
cur in this loop  [1, 2, 1]
cur in this loop  [1, 3, 3, 1]
cur in this loop  [1, 4, 6, 4, 1]
cur in this loop  [1, 5, 10, 10, 5, 1]
对称算法3.1 ['1', '5', '10', '10', '5', '1']

3.2 杨辉三角的Python算法:对称算法的完善

3.1有一个小优化点,当行是奇数时候,中心点被赋值两次,浪费了内存

>>> n = 6  # 我们从n=1开始演算
>>> for i in range(n):
>>>     cur = [1]*(i+1)  #我们这次不再赋值None,而是赋值1,这样就省得再修改首尾的1了 
>>>     
>>>     for j in range(i//2):  #这里把上版的range(i//2)向右平移1,不影响计算次数,
>>>                                 #但i和j在中间点上就有了二倍关系
>>>                                 # i =2, j=0, middle =1 重复
>>>                                 # i =3, j=0,middle =1, 不重复赋值
>>>                                 # i =4, j=0,1,middle =2,重复赋值
>>>         value = pre[j+1] +pre[j]
>>>         cur[j+1] = value 
>>>         
>>>     print("cur in this loop ",cur)
>>>     pre = cur    
>>> 
>>> print("完美的对称算法3.1",["{}".format(i) for i in cur])
cur in this loop  [1]
cur in this loop  [1, 1]
cur in this loop  [1, 2, 1]
cur in this loop  [1, 3, 1, 1]
cur in this loop  [1, 4, 4, 1, 1]
cur in this loop  [1, 5, 8, 1, 1, 1]
完美的对称算法3.1 ['1', '5', '8', '1', '1', '1']
>>> n = 6  # 我们从n=1开始演算
>>> for i in range(n):
>>>     cur = [1]*(i+1)  #我们这次不再赋值None,而是赋值1,这样就省得再修改首尾的1了 
>>>     
>>>     for j in range(1, i//2+1):  #这里把上版的range(i//2)向右平移1,不影响计算次数,
>>>                                 #但i和j在中间点上就有了二倍关系
>>>                                 # i =2, j=0, middle =1 重复
>>>                                 # i =3, j=0,middle =1, 不重复赋值
>>>                                 # i =4, j=0,1,middle =2,重复赋值
>>>         value = pre[j-1] +pre[j]
>>>         cur[j] = value 
>>>         if i == 2*j:
>>>             pass
>>>         else:
>>>             cur[-j-1]=value
>>>         
>>>     print("cur in this loop ",cur)
>>>     pre = cur    
>>> 
>>> print("对称算法3.1",["{}".format(i) for i in cur])
cur in this loop  [1]
cur in this loop  [1, 1]
cur in this loop  [1, 2, 1]
cur in this loop  [1, 3, 3, 1]
cur in this loop  [1, 4, 6, 4, 1]
cur in this loop  [1, 5, 10, 10, 5, 1]
对称算法3.1 ['1', '5', '10', '10', '5', '1']

最后做语法润色,把i==2"j的判断,修改为if i!==2*j

>>> n = 6  # 我们从n=1开始演算
>>> for i in range(n):
>>>     cur = [1]*(i+1)  #我们这次不再赋值None,而是赋值1,这样就省得再修改首尾的1了 
>>>     
>>>     for j in range(1, i//2+1):  #这里把上版的range(i//2)向右平移1,不影响计算次数,
                                #但i和j在中间点上就有了二倍关系
                                # i =2, j=0, middle =1 重复
                                # i =3, j=0,middle =1, 不重复赋值
                                # i =4, j=0,1,middle =2,重复赋值
>>>         value = pre[j-1] +pre[j]
>>>         cur[j] = value 
>>>         if i!= 2*j:
>>>             cur[-j-1]=value
>>>         
>>>     print("cur in this loop ",cur)
>>>     pre = cur    

>>> print("对称算法3.1",["{}".format(i) for i in cur])
cur in this loop  [1]
cur in this loop  [1, 1]
cur in this loop  [1, 2, 1]
cur in this loop  [1, 3, 3, 1]
cur in this loop  [1, 4, 6, 4, 1]
cur in this loop  [1, 5, 10, 10, 5, 1]
对称算法3.1 ['1', '5', '10', '10', '5', '1']
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章