跑溜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']
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章