比較演算法好壞的標準之一是時間複雜度,當然你也可以做空間複雜度的比較,概念非常相似,在本篇就不贅述。而在定義時間複雜度之前,我們要先提及兩個在分析上的預設觀念:

那麼,我們到底要怎麼比較不同演算法或者不同狀況的時間複雜度呢?你應該已經在數學或程式語言中,學過「<」、「≤」、「==」、「≥」以及「>」這五個符號,而比較時間複雜度也有類似的概念,我們直接來看定義,當你把某個演算法的花費和次數的乘積加起來表示成 n 的函數 f(n),而你要拿他跟 g(n) 比較時:

記號與用法 記號讀法 類比的運算 定義(一般版) 定義(極限版) 定義(口語描述版)
f(n) = o(g(n)) Little-oh < o(g(n)) = {f(n): positive constant c, ∃ n0 s.t. 0 ≤ f(n) < c * g(n) ∀ n ≥ n0} limn → ∞ ( f(n) / g(n) ) = 0 對所有正數 c,當 n 夠大的時候,0 ≤ f(n) < c * g(n) 都會成立
f(n) = O(g(n)) Big-oh O(g(n)) = {f(n): ∃ positive constant c and n0 s.t. 0 ≤ f(n) c * g(n) ∀ n ≥ n0} lim supn → ∞ ( f(n) / g(n) ) < ∞ 可以找到一個固定的正數 c,讓 n 只要夠大的時候,0 ≤ f(n) c * g(n) 都會成立
f(n) = Θ(g(n)) Big-theta == Θ(g(n)) = {f(n): ∃ positive constant c1, c2 and n0 s.t. 0 ≤ c1 * g(n) f(n) c2 * g(n) ∀ n ≥ n0} 0 < lim infn → ∞ ( f(n) / g(n) ), and
lim supn → ∞ ( f(n) / g(n) ) < ∞
可以找到兩個固定的正數 c1、c2,讓 n 只要夠大的時候,0 ≤ c1 * g(n) f(n) c2 * g(n) 都會成立
f(n) = Ω(g(n)) Big-omega Ω(g(n)) = {f(n): ∃ positive constant c and n0 s.t. 0 ≤ c * g(n) f(n) ∀ n ≥ n0} lim infn → ∞ ( f(n) / g(n) ) > 0 可以找到一個固定的正數 c,讓 n 只要夠大的時候,0 ≤ c * g(n) f(n) 都會成立
f(n) = ω(g(n)) Little-omega > ω(g(n)) = {f(n): positive constant c, ∃ n0 s.t. 0 ≤ c * g(n) < f(n) ∀ n ≥ n0} limn → ∞ ( f(n) / g(n) ) = ∞ 對所有正數 c,當 n 夠大的時候,0 ≤ c * g(n) < f(n) 都會成立

在上面的表格中:

這些記號在使用上,有下列慣例。此處以 big-oh 說明如下,但另外四個記號亦同:

此外,這些記號有以下性質,雖然這些性質在分析演算複雜度時不一定會直接用上,但若對其有所了解,比較不會在看到不同的寫法時愣住:

因此,對於先前看過的幾個程式片段,其時間複雜度如下(對於其他演算法的分析,會在後續篇章陸續說明):

在上述的說明中,你可能會發現,應該要用 Θ(g(n)) 來描述會比較精確;但在實務上,為了書寫與溝通方便等理由,通常會優先使用 O(g(n))。

複雜度的分析,在實務上也可以幫助你在面對特定問題時,選擇或設計適當的演算法,以求在可接受的時間內處理問題。以目前(2026 年八月)的一般家用電腦規格來說:

上述的說明,也同時代表了複雜度高低的排序:O(n!) > O(2n) > O(n3) > O(n2) > O(n lg n) > O(n) > O(lg n) > O(1)。其中的「>」是「成長較快」的口語表達,比較嚴謹的數學符號應該是「⊋」,代表左邊的集合包含了右邊,且左右兩者不相等,專業講法為「左邊是右邊的真超集」。

而至於 Python 當中,常用內建功能的時間複雜度則列出如下: