算法(Algorithm)是指解題方案的準確而完整的描述,是一系列解決問題的清晰指令(個人理解是一系列解決問題的步驟),算法表明着用系統的方法描述解決問題的策略機制。也就是說,可以對必定規範的輸入,在有限時間內得到所要求的輸出。不一樣的算法可能用不一樣的時間、空間或效率來完成一樣的任務。算法
一個算法的優劣能夠用空間複雜度與時間複雜度來衡量。函數
不一樣的算法對執行程序的結果也許是同樣的,可是執行時間和效率卻有着很大的區別,下面讓咱們來看個例子:性能
問題:a + b + c = 100, a^2 + b^2 = c^2,請計算出全部符合的a, b, c結果。操作系統
import time start_time = time.time() # 注意是三重循環 for a in range(0, 1001): for b in range(0, 1001): for c in range(0, 1001): if a**2 + b**2 == c**2 and a+b+c == 1000: print("a, b, c: %d, %d, %d" % (a, b, c)) end_time = time.time() print("time: %f" % (end_time - start_time)) print("finished!")
結果:blog
a, b, c: 0, 500, 500 a, b, c: 200, 375, 425 a, b, c: 375, 200, 425 a, b, c: 500, 0, 500 time: 214.583347 finished!
程序執行完總共花費了214秒。咱們再來看一個例子:it
import time start_time = time.time() # 注意是兩重循環 for a in range(0, 1001): for b in range(0, 1001-a): c = 1000 - a - b if a**2 + b**2 == c**2: print("a, b, c: %d, %d, %d" % (a, b, c)) end_time = time.time() print("time: %f" % (end_time - start_time)) print("finished!")
結果:table
a, b, c: 0, 500, 500 a, b, c: 200, 375, 425 a, b, c: 375, 200, 425 a, b, c: 500, 0, 500 time: 0.182897 finished!
程序執行完總共花費了0.18秒,這對於第一種方法來講,無疑是一種很大的提高。因此說,算法的好壞對於程序來講是很是重要的。class
所以,咱們能夠得出一個結論:實現算法程序的執行時間能夠反應出算法的效率,即算法的優劣。效率
假設咱們將第二次嘗試的算法程序運行在一臺配置古老性能低下的計算機中,狀況會如何?極可能運行的時間並不會比在咱們的電腦中運行算法一的214.583347秒快多少。import
單純依靠運行的時間來比較算法的優劣並不必定是客觀準確的!
程序的運行離不開計算機環境(包括硬件和操做系統),這些客觀緣由會影響程序運行的速度並反應在程序的執行時間上。那麼如何才能客觀的評判一個算法的優劣呢?
咱們假定計算機執行算法每個基本操做的時間是固定的一個時間單位,那麼有多少個基本操做就表明會花費多少時間單位。算然對於不一樣的機器環境而言,確切的單位時間是不一樣的,可是對於算法進行多少個基本操做(即花費多少時間單位)在規模數量級上倒是相同的,由此能夠忽略機器環境的影響而客觀的反應算法的時間效率。
對於算法的時間效率,咱們能夠用「大O記法」來表示。
「大O記法」:對於單調的整數函數f,若是存在一個整數函數g和實常數c>0,使得對於充分大的n總有f(n)<=c*g(n),就說函數g是f的一個漸近函數(忽略常數),記爲f(n)=O(g(n))。也就是說,在趨向無窮的極限意義下,函數f的增加速度受到函數g的約束,亦即函數f與函數g的特徵類似。
時間複雜度:假設存在函數g,使得算法A處理規模爲n的問題示例所用時間爲T(n)=O(g(n)),則稱O(g(n))爲算法A的漸近時間複雜度,簡稱時間複雜度,記爲T(n)
分析算法時,存在幾種可能的考慮:
對於最優時間複雜度,其價值不大,由於它沒有提供什麼有用信息,其反映的只是最樂觀最理想的狀況,沒有參考價值。
對於最壞時間複雜度,提供了一種保證,代表算法在此種程度的基本操做中必定能完成工做。
對於平均時間複雜度,是對算法的一個全面評價,所以它完整全面的反映了這個算法的性質。但另外一方面,這種衡量並無保證,不是每一個計算都能在這個基本操做內完成。並且,對於平均狀況的計算,也會由於應用算法的實例分佈可能並不均勻而難以計算。
所以,咱們主要關注算法的最壞狀況,亦即最壞時間複雜度。
1)上面第一個列子核心部分:
for a in range(0, 1001): for b in range(0, 1001): for c in range(0, 1001): if a**2 + b**2 == c**2 and a+b+c == 1000: print("a, b, c: %d, %d, %d" % (a, b, c))
T(n) = O(n*n*n) = O(n3)
2)第二個例子核心部分:
for a in range(0, 1001): for b in range(0, 1001-a): c = 1000 - a - b if a**2 + b**2 == c**2: print("a, b, c: %d, %d, %d" % (a, b, c))
T(n) = O(n*n*(1+1)) = O(n*n) = O(n2)
執行次數函數舉例 | 階 | 非正式術語 |
12 | O(1) | 常數階 |
2n+3 | O(n) | 線性階 |
3n^2+2n+1 | O(n^2) | 平方階 |
5log2n+20 | O(logn) | 對數階 |
2n+3nlog2n+19 | O(nlogn) | nlogn階 |
6n^3+2n^2+3n+4 | O(n3) | 立方階 |
2^n | O(2n) | 指數階 |
O(1) < O(logn) < O(n) < O(nlogn) < O(n2) < O(n3) < O(2n) < O(n!) < O(nn)