作算法分析的時候常常用到各類時間複雜度如O(n), O(logn), O(nlogn), O(n^2), ... 它們之間到底有多大的差異呢?下面這張圖是一個直觀的表達:算法
可見,各個經常使用的時間複雜度之間都存在着巨大的差別。從O(nlogn)到O(n),從O(n)到O(logn),都是性能上的巨大飛躍。函數
從另外一個角度而言,大於O(n^2)或O(n^3)時間複雜度的程序實際上都是不可用的。根據維基百科,如今最強的CPU每秒大概可執行428億條指令(4*10^10),而對於一個O(2^n)的程序,當n=100時,就算有2^100條指令,即2^100 = 1.26765 * 10 30條指令。這樣的CPU大概要算1萬億年(10^12)。性能
算法的運行時間一般與下列函數成比例:spa
1 | 大部分程序的大部分指令之執行一次,或者最多幾回。若是一個程序的全部指令都具備這樣的性質,咱們說這個程序的執行時間是常數。 |
log log N | 能夠看做是一個常數:即便N不少,兩次去對數以後也會變得很小 |
logN | 若是一個程序的運行時間是對數級的,則隨着N的增大程序會漸漸慢下來,若是一個程序將一個大的問題分解成一系列更小的問題,每一步都將問題的規模縮減成幾分之一,通常就會出現這樣的運行時間函數。在咱們所關心的範圍內,能夠認爲運行時間小於一個大的常數。對數的基數會影響這個常數,但改變不會太大:當N=1000時,若是基數是10,logN等於3;若是基數是2,logN約等於10.當N=1 00 000,logN只是前值的兩倍。當N時原來的兩倍,logN只增加了一個常數因子:僅當從N增加到N平方時,logN纔會增加到原來的兩倍。 |
N | 若是程序的運行時間的線性的,極可能是這樣的狀況:對每一個輸入的元素都作了少許的處理。當N=1 000 000時,運行時間大概也就是這個數值;當N增加到原來的兩倍時,運行時間大概也增加到原來的兩倍。若是一個算法必須處理N個輸入(或者產生N個輸出),那麼這種狀況是最優的。 |
NlogN | 若是某個算法將問題分解成更小的子問題,獨立地解決各個子問題,最後將結果綜合起來,運行時間通常就是NlogN。咱們找不到一個更好的形容,就暫且將這樣的算法運行時間叫作NlogN。當N=1 000 000時,NlogN大約是20 000 000。當N增加到原來的兩倍,運行時間超過原來的兩倍,但超過不是太多。 |
N平方 | 若是一個算法的運行時間是二次的(quadratic),那麼它通常只能用於一些規模較小的問題。這樣的運行時間一般存在於須要處理每一對輸入數據項的算法(在程序中極可能表現爲一個嵌套循環)中,當N=1000時,運行時間是1 000 000;若是N增加到原來的兩倍,則運行時間將增加到原來的四倍。 |
N三次方 | 相似的,若是一個算法須要處理輸入數據想的三元組(極可能表現爲三重嵌套循環),其運行時間通常就是三次的,只能用於一些規模較小的問題。當N=100時,運行時間就是1 000 000;若是N增加到原來的兩倍,運行時間將會增加到原來的八倍。 |
2的N次方 | 若是一個算法的運行時間是指數級的(exponential),通常它很難在實踐中使用,即便這樣的算法一般是對問題的直接求解。當N=20時,運行時間是1 000 000;若是增加到原來的兩倍時,運行時間將是原時間的平方! |