一、什么是算法分析
程序和算法的區別:
算法是對問題解決的分步描述
程序是采用某種編程語言實現的算法,同一個算法通過不同的程序員采用不同的編程語言,能產生很多程序
算法分析的概念:
算法分析主要就是從計算資源消耗的角度來評判和比較算法
更高效利用計算資源,或者更少占用計算資源的算法,就是好算法
計算資源指標:
一種是算法解決問題過程中需要的存儲空間或內存
另一種是算法的執行時間
運行時間檢測:
1 #累計求和程序的運行時間檢測
2 #迭代法
3 importtime4
5 defsum1(n):6 start =time.time()7 theSum =08 for i in range(1,n+1):9 theSum +=i10 end =time.time()11 return theSum, end -start12
13 for i in range(5):14 print('Sum is %d required %10.7f seconds'%sum1(10000))
n = 10000 時,執行5次的結果為
Sum is 50005000 required 0.0000000seconds
Sumis 50005000 required 0.0009980seconds
Sumis 50005000 required 0.0000000seconds
Sumis 50005000 required 0.0000000seconds
Sumis 50005000 required 0.0009968 seconds
n = 100000 時, 執行5次的結果為
Sum is 5000050000 required 0.0049877seconds
Sumis 5000050000 required 0.0049853seconds
Sumis 5000050000 required 0.0049860seconds
Sumis 5000050000 required 0.0049872seconds
Sumis 5000050000 required 0.0049863 seconds
n = 1000000時,執行5次的結果為
Sum is 500000500000 required 0.0528579seconds
Sumis 500000500000 required 0.0518231seconds
Sumis 500000500000 required 0.0528951seconds
Sumis 500000500000 required 0.0519009seconds
Sumis 500000500000 required 0.0527823 seconds
1 #累計求和程序的運行時間檢測
2 #利用高斯求和公式的無迭代算法
3 importtime4
5 defsum2(n):6 start =time.time()7 theSum = (n * (n+1)) / 2
8 end =time.time()9 return theSum, end -start10
11 for i in range(5):12 print('Sum is %d required %10.7f seconds'%sum2(10000))
n = 10000,100000,1000000時,執行5次的結果時間均相同,為0.0000000 seconds
比較:
第一種迭代算法包含一個循環,這個循環運行次數跟累加值n有關,n增加,循環次數也會增加
第二種無迭代算法運行時間比第一種短很多,運行時間與累計對象n的大小無關
二、大O表示法
算法時間度量指標:
一個算法所實施的操作數量或步驟數可作為獨立于具體程序/機器的度量指標
賦值語句是度量指標的一個合適選擇,一條賦值語句同時包含了(表達式)計算和(變量)存儲兩個基本資源
數量級函數(Order of Magnitude)
基本操作數量函數T(n)的精確值不是特別重要,重要的是T(n)中起決定性因素的主導部分
數量級函數描述了T(n)中隨著n增加而增加速度最快的主導部分
常見的大O數量級函數:
三、"變位詞"判斷問題
1 #解法1:逐字檢查
2
3 defanagramSolution1(s1, s2):4 alist =list(s2)5 pos1 =06 stillOK =True7 while pos1 < len(s1) andstillOK:8 pos2 =09 found =False10 while pos2 < len(alist) and notfound:11 if s1[pos1] ==s2[pos2]:12 found =True13 else:14 pos2 = pos2 + 1
15 iffound:16 alist[pos2] =None17 else:18 stillOK =False19 pos1 = pos1 + 1
20 returnstillOK21
22 print(anagramSolution1('abcd','cabd'))
1 #解法2:排序比較
2
3 defanagramSolution2(s1, s2):4 alist1 =list(s1)5 alist2 =list(s2)6
7 alist1.sort()8 alist2.sort()9 pos =010 matches =True11 while pos < len(s1) andmatches:12 if alist1[pos] ==alist2[pos]:13 pos = pos + 1
14 else:15 matches =False16 returnmatches17
18 print(anagramSolution2('abcde','edcba'))
1 #解法4:計數比較
2
3 defanagramSolution4(s1, s2):4 c1 = [0] * 26
5 c2 = [0] * 26
6 for i ins1:7 pos = ord(i) - ord('a')8 c1[pos] = c1[pos] + 1
9 for j ins2:10 pos = ord(j) - ord('a')11 c2[pos] = c2[pos] + 1
12 k =013 stillOK =True14 while k < 26 andstillOK:15 if c1[k] ==c2[k]:16 k = k + 1
17 else:18 stillOK =False19 returnstillOK20
21 print(anagramSolution4('abcde','edcba'))
四、Python數據類型的性能
1、列表list和字典dict的對比:
2、4種生成前n個整數列表的方法性能比較
1 #4種生成前n個整數列表的方法性能比較
2 from timeit importTimer3
4 deftest1():5 l =[]6 for i in range(1000):7 l = l +[i]8
9 deftest2():10 l =[]11 for i in range(1000):12 l.append(i)13
14 deftest3():15 l = [i for i in range(1000)]16
17 deftest4():18 l = list(range(1000))19
20 t1 = Timer('test1()','from __main__ import test1') #創建一個Timer對象,指定需要反復運行的語句和只需要運行一次的“安裝語句”
21 print('concat %f seconds\n' % t1.timeit(number=10000)) #調用Timer對象的timeit方法,其中可以指定反復運行多少次
22
23 t2 = Timer('test2()','from __main__ import test2')24 print('append %f seconds\n' % t2.timeit(number=10000))25 t3 = Timer('test3()','from __main__ import test3')26 print('comprehension %f seconds\n' % t3.timeit(number=10000))27 t4 = Timer('test4()','from __main__ import test4')28 print('list range %f seconds\n' % t4.timeit(number=10000))
concat 14.517047seconds
append0.859504seconds
comprehension0.517713seconds
list range0.127913 seconds
3、list.pop的計時試驗
#-*- coding: utf-8 -*-
"""Created on Thu Oct 17 20:30:27 2019
@author: wu"""
#list.pop的計時試驗,比較pop()和pop(0)兩種方法
from timeit importTimerimporttimeitimportnumpy as npimportmatplotlib.pyplot as plt
pop0= timeit.Timer('x.pop(0)','from __main__ import x')
popend= timeit.Timer('x.pop()','from __main__ import x')print('pop(0) pop()')
l1=[]
l2=[]for i in range(1000000,10000001,100000):
x=list(range(i))
pt= popend.timeit(number=100)
l1.append(pt)
x=list(range(i))
pz= pop0.timeit(number=100)
l2.append(pz)print('%15.5f,%15.5f' %(pz,pt))
j= np.arange(1000000,10000001,100000)
plt.plot(j,l1,label='pop')
plt.plot(j,l2,label='pop0')
plt.xlabel('n')
plt.ylabel('time(s)')
plt.legend()
plt.show()
4、list和dict的in操作對比
1 #驗證list中檢索一個值,以及dict中檢索一個值的對比
2 importtimeit3 importrandom4 importnumpy as np5 importmatplotlib.pyplot as plt6
7 l1,l2 =[],[]8 n =[]9 for i in range(10000,1000001,20000):10 t = timeit.Timer('random.randrange(%d) in x'%i,'from __main__ import random,x')11 x =list(range(i))12 lst_time = t.timeit(number=100)13 l1.append(lst_time)14 x = {j:None for j inrange(i)}15 d_time = t.timeit(number=100)16 l2.append(d_time)17 print('{},{:10.3f},{:10.3f}'.format(i,lst_time,d_time))18
19 for i in range(10000,1000001,20000):20 n.append(i)21
22 plt.plot(n,l1,'go-',label='list')23 plt.plot(n,l2,'r*-',label='dict')24 plt.xlabel('n')25 plt.ylabel('time')26 plt.legend()27 plt.show()28