時間複雜度與空間複雜度分析

作爲開發人員,我們都希望在完成功能的基礎上讓代碼運行的更快、更省空間,那如何衡量編寫的代碼是否更有效率,這就需要我們學會如何分析代碼時間複雜度和空間複雜度.

什麼是複雜度分析

執行時間和佔用空間是代碼性能的2個評判標準,我們分別用時間複雜度和空間複雜度去描述這2個標準,二者統稱複雜度,複雜度描述的是算法執行時間(或佔用空間)隨數據規模的增長關係.

爲什麼需要複雜度分析

有人可能想問我代碼運行一下不就知道他執行多長時間了嗎,爲什麼還需要複雜度分析,確實你能夠通過這種方法評估出代碼的執行效率,但是這樣會有一些侷限性.

1.測試結果太過於依賴測試環境
同一段代碼在不同處理器的機器上運行結果是顯然不一樣的,這時就不知道應該參考哪個測試結果.
2.測試結果受到數據規模的影響很大
兩段不同的代碼在數據量比較小的時候可能相差甚微,無法真實反映代碼的性能問題.

所以我們需要一個不依賴測試環境同時也不需要有具體的測試數據就能粗略的估計代碼的執行效率的方法,也就是複雜度分析.

如何進行複雜度分析

大O複雜度表示法
先看一段代碼,求1,2,3...n的累加和

int calc(int n) {
  int sum = 0;  //第一行
  for(int i = 1; i <=n; i++) {
    sum = sum + i;
  }
  return sum;
}

我們來評估一下這段代碼的執行時間,假設每行執行的時間一樣,爲row_time.第1行需要一個row_time的執行時間,第2,3行分別執行了n次,所以需要2n*row_time的執行時間,所以這段代碼加起來總共的執行時間爲(2n+1)*row_time,雖然我們並不知道row_time的具體時間,但我們發現代碼的總執行時間T(n)與代碼的執行次數n成正比.我們可以用公式來表示

T(n) = O(f(n))

T(n)代表代碼的總執行時間,f(n)代表代碼的執行次數,O代表T(n)與f(n)成正比.所以上面的例子中,T(n) = O(2n+1),我們可以看出大O時間複雜度表示代碼執行時間隨數據規模的變化趨勢,我們簡稱爲時間複雜度.

當n很大時,公式中的常量,係數都可以忽略不計,並不會對變化趨勢有太大影響,我們只需記下一個最大量級即可,那麼剛剛的例子最後就可以記爲T(n) = O(n)

那以後的代碼如何去分析其時間複雜度呢,我們有以下法則:
1.看代碼執行次數最多的一段,比如循環
2.多段代碼取最大量級,比如單循環和多重循環,應取多重循環的複雜度
3.嵌套代碼複雜度等於嵌套內外代碼複雜度的乘積,比如遞歸和多重循環等

平時我們有一些常用的複雜度級別,比如O(1) (常數階)、O(logn) (對數階)、O(n) (線性階)、O(nlogn) (線性對數階)、O(n²) (平方階)

瞭解了時間複雜度,那麼空間複雜度也不難理解了,時間複雜度表示的是算法執行時間隨數據規模增長的變化關係,那空間複雜度則表示的是算法存儲空間隨數據規模增長的變化關係.

總結

複雜度用來分析算法執行效率與數據規模增長的變化關係,越高階複雜度的的算法執行效率也就越低,上面列舉的複雜度級別從低到高分別爲O(1)、O(logn)、O(n)、O(nlogn)、O(n²).

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章