常見時間複雜度

極為常見

簡介

在演算法中,我們會用 Big-O 來估計一個演算法的時間複雜度,這裡我們列出一些常見的時間複雜度:

  • O(1)O(1) : 常數時間,不論輸入的大小,都可以在一個固定的時間內完成,基本輸出 章節的例子就是這個時間複雜度。
  • O(logn)O(\log n) : 在時間複雜度的領域的 log 通常是指以 2 為底的 log,把一個數字轉成二進位時會用到這個時間複雜度。
  • O(n)O(n) : 線性時間,時間和輸入的大小成正比。
  • O(nlogn)O(n \log n) : 這個時間複雜度通常出現在一些排序演算法上,我們之前介紹的 簡易排序 就是這個時間複雜度。
  • O(n2)O(n^2) : 平方時間,時間和輸入的平方成正比,如果你用兩個迴圈去遍歷一個二維陣列,那麼這個時間複雜度就是 O(n2)O(n^2)

對於不同的複雜度,在數據變大會有不同的增長趨勢,如下圖。

image

時間複雜度與執行時間

仔細觀察上面的圖,我們可以發現,如果複雜度變成指數型會變得增加很快,舉個例子

以大部分的 Judge 系統來說,通常建議以一秒可以跑 10910^9 的簡易計算來估計,那對於一個題目只有 nn 的輸入,我們有 O(n),O(n2),O(nn)O(n), O(n^2), O(n^n) 三種演算法可以解決,我們假設三個方法剛好是分別需要 n,n2,nnn, n^2, n^n 個簡易計算,且不考慮一些硬體上的問題,對於不同的 nn,我們討論它需要跑多久,下面是討論的結果(單位為秒)。

nO(n)O(n)O(n2)O(n^2)O(nn)O(n^n)
110910^{-9}10910^{-9}10910^{-9}
251085 \cdot 10^{-8}2.51082.5 \cdot 10^{-8}2.51082.5 \cdot 10^{-8}
521082 \cdot 10^{-8}41074 \cdot 10^{-7}3.1×1063.1 \times 10^{-6}
1010810^{-8}10710^{-7}1010
10010710^{-7}10910^{-9}1019110^{191}
100010610^{-6}10910^{-9}10299110^{2991}
10510^510410^{-4}1010--
10610^610310^{-3}10001000--

可以看到 O(nn)O(n^n) 的演算法,在 n=100n = 100 時已經需要很大量的時間了,而 O(n2)O(n^2)n=106n = 10^6 也需要不少時間,O(n)O(n) 的則都可以在 1 秒內完成。