數據結構與算法之美(個人筆記)- 算法性能分析_複雜度分析(上)

本人在購買極客學院王爭老師的《數據結構與算法之美》後,覺得裏面的內容還不錯,適合新手入門,故將自己的學習筆記整理了下,做個記錄,供學習使用,另裏面存在個人理解,難保會有差錯,歡迎大家在評論區討論,侵刪。

極客學院專欄地址:https://time.geekbang.org/column/intro/126?gk_activity=0


筆記目錄: https://blog.csdn.net/lxfHaHaHa/article/details/101039494


複雜度分析

設計算法和數據結構的時候,我們會盡量讓代碼運行得更快,更省存儲空間,那麼,用什麼方法來衡量呢?這裏就要用到我們今天要講的內容:時間複雜度分析、空間複雜度分析。

1 時間複雜度

1.1 公式分析

先把公式附上:
在這裏插入圖片描述

  • n代表數據規模的大小
  • T(n)代表代碼執行的時間
  • f(n)表示每行代碼執行的總數之和,因爲是個以n爲自變量的函數,故用f(n)表示
  • O(大寫的o)用來表示T(n)與f(n)成正比

第一個例子:

int cal(int n) {   
	int sum = 0;   
	int i = 1;   
	for (; i <= n; ++i) {     
		sum = sum + i;  
	 }   
	 return sum; 
}

假設每一行代碼運行的時間是一樣的,爲一個時間單位Unit_time,則第2、3、7行各運行了1個Unit_time,第4、5行各運行了n遍,即最後爲2n+3個時間單位。

T(n)=O(f(n))=O(2n+3)

第二個例子:

int cal(int n) {  
	int sum = 0;   
	int i = 1;   
	int j = 1;   
	for (; i <= n; ++i) {    
		 j = 1;    
		  for (; j <= n; ++j) {       
		  	sum = sum +  i * j;     
		  }   
	} 
}

假設每一行代碼運行的時間是一樣的,爲一個時間單位Unit_time,則第2、3、4行各運行了1個Unit_time,第5、6行各運行了n遍,第7、8行各運行了n*n遍,即最後爲2n^2+2n+3個時間單位。

T(n)=O(f(n))=O(2n^2+2n+3)

好了,我們現在引出時間複雜度的概念,所有代碼的執行時間T(n)與每行代碼的執行次數n成正比,即T(n)=O(f(n))
這裏的大O時間複雜度表示法,實際上並不具體表示代碼真正的執行時間,而是表示代碼執行時間隨數據規模增長的變化趨勢,所以,也叫作漸進時間複雜度(asymptotic time complexity),簡稱時間複雜度
另外,當數據量規模n變大,公式中的低階、常量、係數三部分並不左右增長趨勢,所以都可以忽略。我們只需要記錄一個最大量級就可以了。

第一個例子的時間複雜度爲:T(n)=O(n)
第一個例子的時間複雜度爲: T(n)=O(n^2)

1.2 方法

這裏,給了三個trick:

  • 只關注循環次數最多的一段代碼
  • 加法法則:總複雜度等於量級最大的那段代碼的複雜度
  • 乘法法則:嵌套代碼的時間複雜度由嵌套內外的時間複雜度相乘。如上面的例子2是有兩個for循環嵌套起來的,其實可以看成g1(g2(n)),故最後爲n*n
1.3 常見時間複雜度公式

在這裏插入圖片描述

  • 粗略的分爲,多項式量級和非多項式量級,只有O(2^n)和O(n!)是非多項式量級
  • 隨着數據規模n的增加,非多項式量級(NP複雜度)會爆發式增長,耗費時間也越來越多,是效率非常低的算法
  • O(1)是常量級時間複雜度的一種表達方式,不是指只運行了一行,運行了100行、一萬行這種數目一定的都是O(1)
  • O(logn)是對數時間複雜度,因爲係數可以省略,所以log2n、log3n這種都說logn
  • O(m+n)這種是有兩個數據規模存在,因爲事先不能確定二者的量級,故不能簡單的用加法法則表示

2 空間複雜度

既然時間複雜度是指漸進時間複雜度,那麼相似的,空間複雜度也是相似空間複雜度(asymptotic space complexity),表示算法的存儲空間與數據規模之間的增長關係

void print(int n) {
  int i = 0;
  int[] a = new int[n];
  for (i; i = 0; --i) {
    print out a[i]
  }
}

第2行申請一個存儲單位i,第三行申請n個存儲單位,故空間複雜度爲O(n)

Tips: 常見的空間複雜度就是 O(1)、O(n)、O(n2 ),像 O(logn)、O(nlogn) 這樣的對數階複雜度平時都用不到。

3.小結

  • 時間複雜度:漸進時間複雜度,表示算法的執行時間與數據規模之間的增長關係
  • 空間複雜度:漸進空間複雜度,表示算法的存儲空間與數據規模之間的增長關係

在這裏插入圖片描述

4.課後思考

有人說,我們項目之前都會進行性能測試,再做代碼的時間複雜度、空間複雜度分析,是不是多此一舉呢?而且,每段代碼都分析一下時間複雜度、空間複雜度,是不是很浪費時間呢?你怎麼看待這個問題呢?

不是這樣的,我覺得作爲一個合格的開發人員,要對開發有敬畏之心。
像廚師想炒出色香味俱全的菜餚一樣,我們對code也要有追求。
當你打出時間空間複雜度方面都很優秀的代碼的時候,你會覺得很自豪,就像士兵勝戰而歸,美人笑顏相對。
而且,時不時的考慮複雜度方面的問題,對改進算法的方向能有一個大致的把握,對自我能力的提升也是很有幫助的。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章