通常咱們在選擇算法時,都是想要選擇效率最高的算法。那算法的效率,用什麼表示?沒錯!就是用大O表示法。html
PS: 大O表示法中,log即爲log2,後面再也不說明。java
下面以簡單查找和二分查找,在含有n個元素的有序列表中查找其中一個元素爲例,下表總結了咱們發現的狀況。python
使用簡單查找時,最多須要猜想次數與列表長度相同,這被稱爲線性時間,大O表示法爲O(n)。mysql
二分查找則不一樣,最多須要猜想次數爲logn(n爲列表長度),這被稱爲對數時間(log時間),大O表示法爲O(logn)。面試
大O表示法指出了算法的速度有多快。算法
可能你會好奇,它的單位是多少?秒?沒有單位,它並不是指的是時間,而是從增量的角度衡量。sql
列表中查找元素,簡單查找、二分查找的增速以下圖。數組
倘若咱們不知道增速,只知道查找100個元素時的查找時間,猜想10000個元素時的查找時間:學習
對於簡單查找,100個元素時爲100毫秒,簡單推算出10000個元素爲10秒;.net
對於二分查找,100個元素時爲7毫秒,簡單推算出10000個元素爲700毫秒。
PS:簡單推算 10000個元素時的運行時間= 運行時間(100個元素時)* 100
簡單查找的推算是對的,由於的增速是n,而二分查找的推算是錯的,它的增速爲logn,這便不能理所固然簡單推算了。
很顯然,咱們只要知道算法的增速,便能知道它在n個元素中運行的運行時間了,大O表示法就是用來表示算法增速的。
專業描述:大O表示法表示操做數的增速,指出了算法運行時間的增速。
O(㏒n) 對數時間 好比二分查找
O(n) 線性時間 好比簡單查找
O(n*㏒n) 好比快速排序
O(n²) 好比選擇排序
O(n!) 好比旅行者問題
上述的大O表示法都是用來表示時間複雜度,並且一般指的是最壞狀況下的時間複雜度。
一般有如下3種時間複雜度:
以簡單查找爲例子,在n個元素的列表中查找目標元素
最好狀況時間複雜度:目標元素恰好在列表第一個位置,那麼只須要一次就能找到,時間複雜度爲O(1)。
最壞狀況時間複雜度:目標元素在列表最後一個位置或者不在列表中,那麼得須要遍歷完整個列表才能得出結果,時間複雜度爲O(n)。
平均狀況時間複雜度:考慮目標元素在列表中任何位置的狀況。
下面簡單分析下:目標元素若是在列表中,出現的位置有n種狀況,加上不在列表中這一種狀況,總共n+1種狀況。每種狀況下須要遍歷的次數以下表:
目標元素所在位置 | 遍歷次 |
---|---|
第1個位置 | 1 |
第2個位置 | 2 |
第3個位 | 3 |
第n個位置 | n |
不在列表中 | n |
平均遍歷次數=各類狀況遍歷次數相加÷總的狀況數
各類狀況遍歷次數相加爲**((1+2+3...+n)+n),總的狀況數(n+1)**
平均狀況複雜度爲:
((1+2+3...+n)+n)/(n+1)=n(n+3)\2(n+1)
大O表示法,會省略係數、低階、常量,因此平均狀況時間複雜度是O(n)。
空間複雜度是對一個算法在運行過程當中臨時佔用存儲空間大小的一個量度,反映的是一個趨勢。
空間複雜度比較經常使用的有:O(1)、O(n)、O(n²),咱們下面來看看:
空間複雜度 O(1)
若是算法執行所須要的臨時空間不隨着某個變量n的大小而變化,即此算法空間複雜度爲一個常量,可表示爲 O(1)。
例子:
int i = 1; int j = 2; ++i; j++; int m = i + j;
i、j、m 所分配的空間都不隨着處理數據量變化,所以它的空間複雜度 O(1)。
空間複雜度 O(n)
int[] m = new int[n] for(i=1; i<=n; ++i) { j = i; j++; }
第一行new了一個長度爲n的數組m,佔用大小爲n,後面雖然有循環,但沒有再分配新的空間,所以,這段代碼的空間複雜度主要看第一行便可,即O(n)。
PS:O(n²)的異同,再也不累述。
如下常見排序算法的複雜度分析,感覺一下時間複雜度和空間複雜度。
參考:《算法圖解》
http://www.javashuo.com/article/p-rjlsbijy-kb.html
http://www.javashuo.com/article/p-faouqvgr-no.html
文章首發於公衆號【KEN DO EVERTHING】 本公衆號專一於java相關技術,但不限於java、mysql、python、面試技巧、生活感悟等。分享優質博文,技術乾貨,學習資源等優質內容。 歡迎關注,一塊兒學習,共成長!