楊輝三角+優化算法


 1 # 楊慧三角基本實現方式
 2 # triangle = [[1],[1, 1]] # 將所有的結果放在一個大列表中
 3  
 4 # for i in range(2, 6): # 因為已經有兩個了,索引從 2 開始 
 5 #     pre = triangle[i - 1] # 上一個大列表中的 元素
 6 #     cur = [1]           # 當前大列表中的 元素,定義新的元素,並且首位補1
 7 #     for j in range(i - 1): # 對上一個大列表中的元素循環計算,得到當前列表中的 元素(通過循環得到循環次數)
 8 #         cur.append(pre[j] + pre[j + 1]) # 上一個元素中前一項 + 后一項,就是當前元素
 9 #     cur.append(1) # 尾部補 1
10 #     triangle.append(cur)
11 # print(triangle)
12 
13 # 變體:
14 
15 # triangle = [[1]] # 將所有的結果放在一個大列表中
16  
17 # for i in range(1, 6): # 因為已經有兩個了,索引從 2 開始 
18 #     pre = triangle[i - 1] # 上一個大列表中的 元素
19 #     cur = [1]           # 當前大列表中的 元素,定義新的元素,並且首位補1
20 #     for j in range(i - 1): # 對上一個大列表中的元素循環計算,得到當前列表中的 元素(通過循環得到循環次數)
21 #         cur.append(pre[j] + pre[j + 1]) # 上一個元素中前一項 + 后一項,就是當前元素
22 #     cur.append(1) # 尾部補 1
23 #     triangle.append(cur)
24 # print(triangle)
25 
26 # 再變體
27 # triangle = [] # 將所有的結果放在一個大列表中
28  
29 # for i in range(6): # 因為已經有兩個了,索引從 2 開始     
30 #     cur = [1]  # 當前大列表中的 元素,定義新的元素,並且首位補1  
31 #     triangle.append(cur)
32 #     if i == 0: continue
33 #     pre = triangle[i-1]    
34 #     for j in range(i - 1): # 對上一個大列表中的元素循環計算,得到當前列表中的 元素(通過循環得到循環次數)
35 #         cur.append(pre[j] + pre[j + 1]) # 上一個元素中前一項 + 后一項,就是當前元素
36 #     if i > 0:
37 #         cur.append(1) # 尾部補 1
38     
39 # print(triangle)
 1 # 補零法 
 2 # # NO 1 只補一個:右側補零
 3 # 1 0    
 4 # 1 1 0   # 上一位的最后一項 即-1 位置 + 0 位置
 5 # 1 2 1 0
 6 # 1 3 3 1 0
 7 # triangle = [[1],[1, 1]] 
 8  
 9 # for i in range(2, 5): 
10 #     pre = triangle[i - 1] + [0] # 注 ,這里不能用append() ,因為返回None
11 #     cur = []           
12 #     for j in range(i + 1): # 當i = 2 時,測試得需要循環 3 次,所以 i + 1
13 #         cur.append(pre[j - 1] + pre[j]) # j = 0 ,pre[-1] + pre[0]   j = 1 ,pre[0] + pre[1]
14 #     triangle.append(cur)
15 # print(triangle)
16 
17 
18 # triangle = [[1]] 
19 # for i in range(1, 5): 
20 #     pre = triangle[i - 1].copy() # 淺拷貝
21 #     pre.append(0) # 補零
22 #     cur = []  # 如果不需要之前的結果,這里用cur.clear() ,否則內存空間產生很多的垃圾。         
23     
24 #     for j in range(i + 1): # 等價  while offset <= i
25 #         cur.append(pre[j - 1] + pre[j])   # cur.append(pre[offset - 1] + pre[offset]) 
26 #     triangle.append(cur)
27 # print(triangle)
28 
29 
30 
31 # -------------------------------------------------------------------------------------
32 
33 
34 # # NO 2 兩側補零
35 # 0 1 0    
36 # 0 1 1 0   # 上一位  位置0 + 位置 1
37 # 0 1 2 1 0
38 # 0 1 3 3 1 0
39 
40 # triangle = [[1],[1, 1]]  
41 # for i in range(2, 5): 
42 #     pre = [0] + triangle[i - 1] + [0] # [0,1,1,0]
43 #     cur = []           
44 #     for j in range(i + 1):# i = 2  , 0.1
45 #         cur.append(pre[j]+ pre[j+1])    #j = 0 pre[0]+pre[1, j = 1 pre[1] + pre[2]
46 #     triangle.append(cur)
47 # print(triangle)
48 
49 
50 # # 變形
51 # triangle = [[1]]  
52 # for i in range(1, 5): 
53 #     pre = [0] + triangle[i - 1] + [0] # [0,1,1,0]
54 #     cur = []           
55 #     for j in range(i + 1):# i = 2  , 0.1
56 #         cur.append(pre[j]+ pre[j+1])    #j = 0 pre[0]+pre[1, j = 1 pre[1] + pre[2]
57 #     triangle.append(cur)
58 # print(triangle)
59 
60 # # 再變形
61 # triangle = [] 
62 # for i in range(5): 
63 #     if i == 0:
64 #         cur = [1]
65 #         triangle.append(cur)
66 #         continue
67 #     pre = [0] + triangle[i - 1] + [0]
68 #     cur = []           
69 #     for j in range(i + 1):
70 #         cur.append(pre[j]+ pre[j+1])    
71 #     triangle.append(cur)
72 # print(triangle)
 1 # 對稱法:
 2 # 1               
 3 # 1 1             
 4 # 1 2  1            i = 2   計算 1 次   2//2    奇數行 中間的數  j=1 i=2 i=2j
 5 # 1 3  3 1          i = 3        1      3//2    
 6 # 1 4  6 4 1        i = 4        2      4//2    奇數行 中間的數  j=2 i=4  i=2j
 7 # 1 5 10 10 5 1     i = 5        2      5//2    
 8 # 把所有行都保存了,這樣往后越來越占空間
 9 # n = 4
10 # triangle = [[1],[1,1]]
11 
12 # for i in range(2,8):# 2    3 4
13 # #     cur = [1]
14 # #     for j in range(i):
15 # #         cur.append(1 if j == i-1 else 0)     
16 #     cur = [1] * (i + 1) # i = 2,cur=[1,1,1]  i=3 cur=[1,1,1,1]  i=4 cur=[1,1,1,1,1] 
17 #     pre = triangle[i - 1] # pre=[1,1]   pre=[1,2,1] pre [1,3,3,1]
18     
19 #     for j in range(i // 2):  # j = 0   j= 0 j=0,1
20 #         val = pre[j] + pre[j + 1]  # pre[0]+pre[1] 4  pre[1]+pre[2] 6
21 #         cur[j + 1] = val # 覆蓋第二項
22 # #       if i != 2 * j:  # 跳過 i = 2*j 的一項
23 #         cur[-j - 2] = val # cur[-2]=2   cur[-3] = 6  覆蓋之前的值           
24 #     triangle.append(cur)
25 # print(triangle)
26 
27 # i = 2  1 2 1      0,1,2
28 # i = 3  1 3 3 1    0.1.2.3  j=[0]  后面 -1
29 # I = 4  1 4 6 4 1   j=[0,1]  后面 -2  -1   -j-1
30 
31 
32 
33 
34 
35 # 優化:降低空間復雜度(單行覆蓋) 36 37 # 單行覆蓋法
38 # n = 5
39 # row = [1] * n
40 
41 # for i in range(n):
42 #     offset = n - i # 比如n = 4,i = 3,n-i 就是去除左側用不到的
43 #     z = 1
44 #     for j in range(i//2):# i=2,j=0  # i=3,j=0      
45 #         val = z + row[j + 1]  # val=1+row[1] # val=1+row[1]=3
46         
47 #         # 記錄上一該位置的值,比如 i = 3時,如果不記錄,會被val覆蓋
48 #         # 此時計算下一個,3 = 3 + 1而不是 2 + 1
49 #         z = row[j + 1] # z=row[1] # z=row[1]=2
50                         
51 #         row[j + 1] = val # row[1]=2 #row[1]=2
52 #         if i != 2 * j:# 2!=0 # 3!=0
53 #             row[-j - 1 - offset] = val # row[-4]=2 # row[-3]=3 
54         
55 #     print(row[:i + 1])
56     
57 
58 # 1    1 1 1 1 
59 # 1 1    1 1 1  ---- 1 2 1 1 1  ---  
60 # 1 2 1    1 1
61 # 1 3 3 1    1

 

 1 '''
 2 求楊輝三角某一個的某個值
 3     思路1:使用之前的辦法,將三角求出來,在找某行的某個值
 4     思路2: 利用數學公式,即是組合數的值(二項式展開式的系數,(a + b)** n)
 5 
 6 '''
 7 # NO:1 
 8 # 兩行來處理 ,這是又一種求楊慧三角的算法,通過兩行相互交替
 9 # m = 6
10 # k = 2
11 
12 # oldline = []
13 # for i in range(m): 
14 #     newline = [1] * (i + 1)# 3 [1,1,1]  [1,1] 
15     
16 #     if i < 2: 
17 #         oldline = newline
18 #         continue
19     
20 #     for j in range(i - 1): # 0,1
21 #         newline[j + 1] = oldline[j] + oldline[j + 1]
22 #     oldline = newline
23 # print(newline)
24 # print(newline[k-1])
25 
26 # 優化:
27 # m = 6
28 # k = 2
29 
30 # oldline = []
31 # for i in range(m): 
32 #     newline = [1] * (i + 1)
33 #     for j in range(i - 1): 
34 #         newline[j + 1] = oldline[j] + oldline[j + 1]
35 #     oldline = newline
36 # print(newline)
37 # print(newline[k-1])
38 
39 
40 
41 # NO.2
42 # 利用組合公式 C(n,m) = n!/(m!*(n-m)!)
43 # m = 6
44 # k = 2
45 
46 # n = m - 1 # 這塊可以不寫,主要分析用
47 # r = k - 1
48 # d = m - k
49 
50 # f = 1
51 # offset = [] # 用來放三個結果
52 
53 # for i in range(1, n + 1): # 每一行都是從第一個數 1 開始
54 #     f *= i  
55 #      因為分子部分肯定包含了分子,所以算到分子的時候記錄下來,知道算到分子大小的階乘位置
56 #     if i == (m - k):
57 #         offset.append(f)
58 #     if i == (k - 1):
59 #         offset.append(f)
60 #     if i ==(m - 1):
61 #         offset.append(f)
62 # print(int(offset[2]/(offset[1] * offset[0])))

 

 

 

總結:

基本實現方式的編程思想:
1、對於楊慧三角,前兩行比較特殊,先把前兩行提取出來。
2、利用大列表,將所有的數據放在該列表中。
3、利用列表的性質,控制上一行和當前行
4、首尾補 1
5、用到雙層for循環,第一層控制行,第二層控制運算。
6、對於規律性的問題,先測試前幾行,測試通過后,在測試后續基本沒有大問題,結構需要在調整一下。
7、變體,即結構的調整,盡量將特殊行也加入到循環中,注意是否需要條件判斷這些特殊行
8、注意使用一些簡化結構:if i == 0: continue
補零法:
1、分析楊慧三角,可以看出,上一行前后相加,,就是下一行的值,而首尾都是1,所以可以考慮首尾補零的方法。
2、補零可以有兩種,首尾都補,一側補
3、補零,注意雖然使用列表,但是注意列表返回值是否是None,還是新列表。
4、這里使用了+ 或淺拷貝追加0 兩種方式
5、cur = [] 如果不需要之前的結果,這里用cur.clear() ,否則內存空間產生很多的垃圾。
6、for j in range(i + 1):
cur.append(pre[j - 1] + pre[j])
# 等價 while offset <= i
# cur.append(pre[offset - 1] + pre[offset])

對稱法 and 單行覆蓋法:
1、 對結果分析可以看出,只需要計算左側的即可,所以考慮使用對稱法
2、這里用到的主要思想是:
- 直接開辟一定的空間,上面的方法,每次都把之前的保存下來,按照需求,不需要,所以直接操作同一個列表即可
- 開辟一定大小的空間,對於楊慧三角來說,通過結果規律發現,首尾都是1,中間其他數字,所以可以開辟這樣的空間:首尾為1,其他位為0.或者最好的方式是都為1,產生新的數值,覆蓋原有的數字即可。
# # cur = [1]
# # for j in range(i):
# # cur.append(1 if j == i-1 else 0)
or
# # cur = [1] * (i + 1) # i = 2,cur=[1,1,1] 
3、計算時,只計算左側一般,而且有奇數行,會有一個中間數,此時 i = 2j, 因為要對稱,所以算完前半部分,在跳過這個值(先判斷不等於后),在利用列表索引賦值。
4、注意點:對單行運算,前一次的運算結果,會覆蓋原來位置的值,所以需要一個臨時變量接受這個值,以便下次計算使用。

 

注:要時刻注意內存的使用,當內存被占用到一定的閾值,就會出道GC 對內存清理,此時程序會暫停,降低了運行效率,所以根據具體情況使用列表,是一次性給,還是用一次刪一次。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM