1. 程式人生 > >資料結構與演算法筆記(二)複雜度分析

資料結構與演算法筆記(二)複雜度分析

2. 複雜度分析

2.1 什麼是複雜度分析

資料結構和演算法的本質:快和省,如何讓程式碼執行得更快、更省儲存空間。

演算法複雜度分為時間複雜度和空間複雜度,從執行時間和佔用空間兩個維度來評估資料結構和演算法的效能。

複雜度描述的是演算法執行時間(或佔用空間)與資料規模的增長關係,越高階複雜度的演算法,執行效率越低。

2.2 為什麼需要複雜度分析

如果採用效能測試,測試結果非常依賴測試環境和受資料規模的影響很大。而複雜度分析有不依賴執行環境、成本低、效率高、易操作、指導性強的特點。

2.3 如何進行復雜度分析

2.3.1 大O表示法

不是程式碼真正執行的時間,而是表示程式碼執行時間隨資料規模增長的變化趨勢,叫作漸進時間複雜度,簡稱時間複雜度。

T ( n ) = O ( f (

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

T ( n )

T(n) 表示程式碼執行的時間; n n 表示資料規模的大小; f ( n ) f(n) 表示每行程式碼執行的次數總和; O O 表示程式碼的執行時間 T ( n ) T(n) f ( n ) f(n) 表示式成正比。

2.3.2 時間複雜度

  • 只關注迴圈執行次數最多的一段程式碼
  • 加法規則:總複雜度等於量級最大的那段程式碼的複雜度
  • 乘法規則:巢狀程式碼的複雜度等於巢狀內外程式碼複雜度的乘積
  • 程式碼複雜度由兩個資料規模決定的,不能簡單利用加法規則,複雜度為 O ( m + n ) O(m+n)

幾種常見時間複雜度

  • 多項式量級:

    • 常量階 O ( 1 ) O(1) :程式碼執行時間不隨n的增大而增長
    • 對數階 O ( l o g n ) O(log n)
    • 線性階 O ( n ) O(n)
    • 線性對數階 O ( n l o g n ) O(nlogn)
    • 平方階 O ( n 2 ) O(n^2) 、立方階 O ( n 3 ) O(n^3) \cdots k次方階 O ( n k ) O(n^k)
  • 非多項式量級:當資料規模越來越大時,演算法執行時間會急劇增加,非常低效

    • 指數階 O ( 2 n ) O(2^n)
    • 階乘階 O ( n ! ) O(n!)

2.3.3 空間複雜度

漸進空間複雜度,表示演算法的儲存空間與資料規則之間的增長關係。

常見的空間複雜度:

  • O ( 1 ) O(1)
  • O ( n ) O(n)
  • O ( n 2 ) O(n^2)

2.4 時間複雜度情況

  • 最好情況時間複雜度(best case time complexity)

  • 最壞情況時間複雜度(worse case time complexity)

  • 平均情況時間複雜度(average case time complexity)

  • 均攤時間複雜度(amortized time complexity)

2.4.1 最好情況時間複雜度

在最理想的情況下,執行這段程式碼的時間複雜度。

以下面這段程式碼為例,

// n 表示陣列 array 的長度
int find(int[] array, int n, int x) {
  int i = 0;
  int pos = -1;
  for (; i < n; ++i) {
    if (array[i] == x) {
       pos = i;
       break;
    }
  }
  return pos;
}

如果要查詢的變數x正好是陣列的第一個元素,對應的時間複雜度即為最好情況時間複雜度。

2.4.2 最壞情況時間複雜度

在最糟糕的情況下,執行這段程式碼的時間複雜度。

以剛剛舉的例子,如果陣列中沒有要查詢的變數x,需要把整個陣列都遍歷一遍時,此時對應的時間複雜度即為最壞情況時間複雜度。

2.4.3 平均情況時間複雜度

也叫加權平均時間複雜度或期望時間複雜度,用程式碼在所有情況下執行的次數的加權平均值表示。

假設在陣列中與不在陣列中的概率都為 1 2 \frac{1}{2} ,且要查詢的資料出現在 0~n-1 這 n 個位置的概率也是一樣的,都為 1 n \frac{1}{n} 。因此,根據概率乘法法則,要查詢的資料出現在 0~n-1 中任意位置的概率是 1 2 n \frac{1}{2n} 。那麼平均情況複雜度的計算過程為:

1 × 1 2 n + 2 × 1 2 n + 3 × 1 2 n + + n × 1 2 n + n × 1 2 = 3 n + 1 4 1\times\frac{1}{2n} +2\times \frac{1}{2n} + 3\times \frac{1}{2n} + \cdots +n\times \frac{1}{2n} + n\times \frac{1}{2}=\frac{3n+1}{4}​

2.4.4 均攤時間複雜度

對一個數據結構進行一組連續操作中,大部分情況下時間複雜度都很低,只有個別情況下時間複雜度比較高,而且這些操作出現的頻率是非常有規律的,之間存在前後連貫的時序關係。此時,就可以將這一組操作一起分析,將較高時間複雜度的那次操作的耗時,平攤到其他那些時間複雜度比較低的操作上。能夠應用均攤時間複雜度分析的場合,一般均攤時間複雜度等於最好情況時間複雜度。

均攤時間複雜度應用的場景特殊、有限,可以看成一種特殊的平均時間複雜度。

2.4.5 總結

只有同一塊程式碼在不同的情況下,時間複雜度有量級的差距,我們才會使用這幾種複雜度表示法來區別。一般情況下,使用一個複雜度就可以滿足需求。