一文說懂算法時間空間複雜度分析

什麼是數據結構,又什麼是算法

百度百科釋義:算法(Algorithm)是指解題方案的準確而完整的描述,是一系列解決問題的清晰指令,算法表明着用系統的方法描述解決問題的策略機制...一個算法的優劣能夠用空間複雜度與時間複雜度來衡量。java

懂了沒?其實我也懵逼。這些定義都很抽象,對理解這兩個概念並無實質性的幫助,你要是深究反而容易陷進誤區算法

表達從簡單開始~bash

形象地說,數據結構就是指存儲數據的結構。算法就是操做數據的方法。數據結構

圖書館你總去過吧,圖書館員爲了方便讀者查找書籍,會把書本分門別類的放好並按規律編號。這裏排放規律的書籍其實就是一種數據結構數據結構和算法

那你怎麼來找書呢?是一本一本的找;根據 人文與社科,電子與信息技術,城市規劃與建設 書館尋找;仍是到電腦搜索書名再拿着獲得的編號找... 這就是 查找的算法性能

數據結構和算法又爲何經常要一塊兒講

那是由於算法只能做用於特定的數據結構,而數據結構又會根據自身特色推演出特定的算法單元測試

好比剛纔的例子:學習

  • 按規律編號的書籍,能夠一本一本找;分書館找;按索引找;
  • 亂堆連放的書籍,你就只能一本一本找了

數據結構是隻是種堆放數據的方式,數據結構與算法研究的是如何快和省的問題,你不根據數據結構的規律特色談算法是沒用的。測試

時間/空間複雜度分析又是什麼

剛纔咱們說到:數據結構與算法研究的是如何快和省地解決問題 —— 那如何纔算快,怎樣纔是省呢。
因此如何衡量算法的 執行效率,使用空間 是個很重要的標準 —— 這就須要咱們的 時間複雜度分析空間複雜度分析
它有多重要呢 —— 我感受這就是數據結構與算法課程裏的半壁江山,以後說的具體結構和算法都是圍着這個標準轉的spa

爲何須要時間/空間複雜度分析

算法效率的度量方法內有一種就叫過後統計方法,說白了就是:寫個單元測試跑一遍算法,就消耗多少內存,多少時間。

很簡單直接。可問題是這個單元測試

  • 在Intel Core i九、Intel Core i3 處理器上跑出的性能不同
  • 數據量大、數據量小跑出來的性能也不同

這不就是擺明挖坑給本身,就看何時跳嘛。

因此咱們須要一個不依賴具體測試環境、具體數據,就能夠粗略估計算法執行效率的方法。

那具體是個怎樣的方法呢

大 O 複雜度表示法

無關緊要的解釋:大 O 時間複雜度表示法表示代碼執行時間隨數據規模增加的變化趨勢,也叫漸進時間複雜度,簡稱時間複雜度。

咱們從一段普通的java代碼提及~

1   int i;
2   for( i=0; i < n; i++ ){
3       sum = sum + i;
4   }
複製代碼

執行狀況:

  • 第 1 行,執行了一遍;
  • 第 二、3 行,執行了n遍;

因此這段普通的java代碼執行次數是:2n+1

咱們假設每行語句的執行一遍的時間是一個單位時間(unit_time)。因此整段代碼總的執行時間:

T(n) = (2n+1)*unit_time
複製代碼

儘管咱們不知道 unit_time 的具體值,可是經過公式,咱們知道全部代碼的執行時間 T(n) 與每行代碼的執行次數 n 成正比。

所以咱們能夠引出這麼條公式:T(n) = O(f(n)) (不用記,繼續往下看),因而普通的java代碼執行時間會演變成:

T(n) = O(2n+1)

而後時間複雜度分析只關注執行次數最多的那段代碼,且忽略係數、常量、對數的「底」。因而最後普通的java代碼的時間複雜度是:O(n)

時間複雜度分析,說到這裏基本概念就說完。撒花~~ 不過還有兩個容易產生誤會的點,須要三申五令:

1. 只關注執行次數最多的那段代碼

1   int i, j, q, n = 100;
2   for ( q=0; q < n; q++ ) { 
3       printf(「I love u\n」);
4   } 
5   
6   for( i=0; i < n; i++ ){
7       printf(「I love u」); 
8       for( j=0; j < n; j++ ){
9           printf(「 three thousand times\n」);
10      }
11  }
複製代碼

執行狀況:

  • 第 1 行,執行了一遍;
  • 第 二、3 行,執行了n遍;
  • 第 六、7 行,執行了n遍;
  • 第 八、9 行,執行了nn遍; 因此這段代碼執行次數是:1+n+n+(nn),由於:

時間複雜度分析只關注執行次數最多的那段代碼,且忽略係數、常量、對數的「底」

因此最後的時間複雜度爲:O(n2) ...(n的2次方)

2. 關注代碼執行次數

時間複雜度分析,咱們本質分析的是什麼?—— 時間嗎?不,咱們看的是代碼執行次數。

假設每行語句的執行一遍的時間是一個單位時間(unit_time)—— 是由於有了這個假設,咱們才把次數換單位時間,從而推導出O(n)

爲何專門提這一點呢?咱們舉個例子:

1   int i=0; 
2   while (i < n) { 
3       i = i * 2; 
4   }
複製代碼

若是你說是O(n),恭喜,我賞你一丈紅。答錯了!認真看我推導... 咱們假設 x 爲執行次數,那麼上面代碼 x 和 n 的關係爲:

因此執行次數與 n 的關係爲:

因爲 一次執行次數等於一個單位時間,且對數的「底」。因此最後的時間複雜度爲

空間複雜度分析

空間複雜度分析和時間複雜度分析相似,你只須要把 一次執行次數等於一個單位內存大 O 複雜度表示法重推一遍就會啦~

結語

複雜度分析並不難,關鍵在於多練。從低階到高階有:O(1)、O(logn)、O(n)、O(nlogn)、O(n2)。

雖然 複雜度分析還有最好、最壞、均攤(平均)複雜度分析。 但我的感受 你掌握上面的複雜度分析,再加個均攤複雜度分析。學習工做就夠用了。

而均攤複雜度分析,個人理解是

多少種狀況 被 各狀況的「時間複雜度之和」相除

歡迎點贊+關注,咱們下次再聊

相關文章
相關標籤/搜索