本系列是極客時間中前 Google 工程師王爭《資料結構與演算法之美》專欄的學習筆記,想加強資料結構及演算法能力的同學可以直接購買此專欄,跳轉連結在此
複雜度分析是整個演算法學習的精髓,只要掌握了它,資料結構與演算法的內容基本上就掌握了一半
什麼是複雜度分析
資料結構和演算法解決是如何讓計算機更快時間、更省空間的解決問題,因此需從執行時間和佔用空間兩個維度來評估資料結構和演算法的效能。
複雜度描述的是演算法執行時間或佔用空間與資料規模的增長關係。
如何進行復雜度分析
大 O 表示法
來源
演算法的執行時間與每行程式碼的執行次數成正比,用 T(n) = O(f(n)) 表示。其中 T(n) 表示演算法執行總時間,f(n) 表示每行程式碼執行總次數,而 n 往往表示資料的規模
特點
以時間複雜度為例,由於時間複雜度描述的是演算法執行時間與資料規模的增長變化趨勢,所以常量階、低階以及係數實際上對這種增長趨勢不產生決定性影響,故在做時間複雜度分析時忽略這些項。
複雜度分析法則
只關注迴圈執行次數最多的一段程式碼
在分析一個演算法、一段程式碼的時間複雜度的時候,也只關注迴圈執行次數最多的那一段程式碼就可以了
加法法則:總複雜度等於量級最大的那段程式碼的複雜度
如果 T1(n)=O(f(n)), T2(n)=O(g(n));
那麼 T(n) = T1(n) + T2(n) = max(O(f(n)), O(g(n))) = O(max(f(n), g(n)))
乘法法則:巢狀程式碼的複雜度等於巢狀內外程式碼複雜度的乘積
可以把乘法法則看成是巢狀迴圈:
如果 T1(n) = O(f(n)), T2(n) = O(g(n))
那麼 T(n) = T1(n) * T2(n) = O(f(n)) * O(g(n)) = O(f(n) * g(n))
總結
- 單段程式碼看高頻:比如迴圈
- 多段程式碼取最大:比如一段程式碼中有單迴圈和多重迴圈,那麼取多重迴圈的複雜度
- 巢狀程式碼求乘機:比如遞迴、多重迴圈等
- 多個規模求加法:比如方法有兩個引數控制兩個迴圈的次數,那麼這時就取二者複雜度相加
常用複雜度級別
-
多項式階:隨著資料規模的增長,演算法的執行時間和空間佔用,按照多項式的比例增長。包括, O(1)(常數階)、O(logn)(對數階)、O(n)(線性階)、O(nlogn)(線性對數階)、O(n^2)(平方階)、O(n^3)(立方階)
-
非多項式階:隨著資料規模的增長,演算法的執行時間和空間佔用暴增,這類演算法效能極差。包括, O(2^n)(指數階)、O(n!)(階乘階)
最壞、最好、平均及均攤時間複雜度
最好時間複雜度
程式碼在最理想的情況下執行的時間複雜度
最壞時間複雜度
程式碼在最壞情況下執行的時間複雜度
平均時間複雜度
用程式碼在所有情況下執行的次數加權平均值表示
均攤時間複雜度
在程式碼執行的所有複雜度情況中絕大部分是低階別的複雜度,個別情況是高階別複雜度且發生具有時序關係時,可以將個別高階別複雜度均攤到低階別複雜度上。基本上均攤結果就等於低階別複雜度
宣告
本文更多是本人學習筆記之用,更多詳細的講解及程式碼,請檢視極客時間專欄《資料結構與演算法之美》