时间复杂度

在计算机科学中，算法的时间复杂度（time complexity）是一个函数，用于定性描述该算法的运行时间，这是一个代表算法输入值的字符串的长度的函数。时间复杂度常用大O符号表述，且不计入函数的低阶项和首项系数。使用这种方式时，时间复杂度可被称为是渐近时间复杂度，即考察输入值大小趋近无穷时的情况。例如，如果一个算法对于任何大小为 n （n 需大于 n0 ）的输入，至多需要  的时间运行完毕，则该算法的渐近时间复杂度是 O(n3)。

為了計算時間複雜度，通常會估計算法的操作單元數量，每個單元執行的時間都是相同的。因此，總運行時間和算法的操作單元數量最多相差一个常量系数。

相同大小的不同輸入值仍可能造成算法的執行時間不同，因此通常使用算法的，記為 T(n) ，定義為任何大小的輸入  n 所需的最大執行時間。另一種較少使用的方法是，通常有特別指定才會使用。時間複雜度可以用函數 T(n) 的自然特性加以分類，舉例來說，有著 T(n) = O(n) 的算法被稱作「線性時間算法」；而 T(n) = O(Mn) 和 Mn= O(T(n)) ，其中 M ≥ n > 1 的算法被稱作「指數時間算法」。

 常见时间复杂度列表 
以下表格統整了一些常用的時間複雜度類別。表中，poly(x) = xO(1)，也就是 x 的多項式。

 名称  复杂度类  运行时间（）  运行时间举例  算法举例 常数时间     10  判断一个二进制数的奇偶 反阿克曼时间      并查集的单个操作的平摊时间 迭代对数时间      分散式圓環著色問題 对数对数时间      有界优先队列的单个操作 对数时间  DLOGTIME    ，    二分搜索 幂对数时间       （小于1次）幂时间   ，其中  ， K-d树的搜索操作 线性时间       无序数组的搜索 线性迭代对数时间      的算法 线性对数时间     ，  最快的比较排序 二次时间         冒泡排序、插入排序 三次时间        矩阵乘法的基本实现，计算偏相关 多项式时间  P      ，，  线性规划中的，AKS质数测试 准多项式时间  QP   关于有向最著名的近似算法 次指数时间（第一定义） SUBEXP  ，对任意的ε > 0    假設複雜性理論推測，BPP 包含在 SUBEXP 中。 次指数时间（第二定义）   2o(n）  2n1/3  用於整數分解與的著名演算法  指数时间  E  2O(n)  1.1n, 10n  使用动态规划解决旅行推销员问题 阶乘时间   O(n!)  n!  通过暴力搜索解决旅行推销员问题 指数时间  EXPTIME  2poly(n)  2n, 2n2  双重指数时间  2-EXPTIME  22poly(n)  22n  在中決定一個給定描述的真實性 

常数时间

若对于一个算法，的上界与输入大小无关，则称其具有常数时间，记作时间。一个例子是访问数组中的单个元素，因为访问它只需要一条指令。但是，找到无序数组中的最小元素则不是，因为这需要遍历所有元素来找出最小值。这是一项线性时间的操作，或称时间。但如果预先知道元素的数量并假设数量保持不变，则该操作也可被称为具有常数时间。

虽然被称为「常数时间」，运行时间本身不须与问题规模无关，但它的上界必须是与问题规模无关的确定值。举例，「如果a > b则交换a、b的值」这项操作，尽管具体时间会取决于条件「a > b」是否满足，但它依然是常数时间，因为存在一个常量t使得所需时间总不超过t。

以下是一个常数时间的代码片段：

 int index = 5;
 int item = list[index];
 if (condition true) then
    perform some operation that runs in constant time
 else
    perform some other operation that runs in constant time
 for i = 1 to 100
    for j = 1 to 200
       perform some operation that runs in constant time

如果，其中是一个常数，这记法等价于标准记法。

对数时间
若算法的T(n) = O(log n)，则称其具有对数时间。计算机使用二进制的记数系统，对数常常以2为底（即log2 n，有时写作lg n）。然而，由对数的换底公式，loga n和logb n只有一个常数因子不同，这个因子在大O记法中被丢弃。因此记作O（log n），而不论对数的底是多少，是对数时间算法的标准记法。

常见的具有对数时间的算法有二叉树的相关操作和二分搜索。

对数时间的算法是非常有效的，因为每增加一个输入，其所需要的额外计算时间会变小。

快速幂 就是一個經典例子。要計算n次方只需要O(log n)的時間。

long long power(long long p, long long n)
{
	long long ans = 1;
	while (n)
	{
		if (n & 1) ans = (ans * p) % Mod;
		p = p * p % Mod;
		n >>= 1;
	}
	return ans;
}

幂对数时间
对于某个常数k，若算法的T(n) = O((log n)k)，则称其具有幂对数时间。例如，矩阵链排序可以通过一个PRAM模型.被在幂对数时间内解决。

次线性时间
对于一个演算法，若其符合T(n) = o(n)，则其时间复杂度为次线性时间（sub-linear time或sublinear time）。实际上除了符合以上定义的演算法，其他一些演算法也拥有次线性时间的时间复杂度。例如有O(n½) 演算法。

常见的非合次线性时间演算法都采用了诸如平行处理（就像NC1 matrix行列式计算那样）、非古典處理（如同葛羅佛搜尋那樣），又或者选择性地对有保证的输入结构作出假设（如幂对数时间的二分搜尋）。不过，一些情况，例如在头 log(n) 位元中每个字串有一个位元作为索引的字串组就可能依赖于输入的每个位元，但又符合次线性时间的条件。

「次线性时间演算法」通常指那些不符合前一段的描述的演算法。它们通常运行于传统电脑架構系列并且不容许任何对输入的事先假设。但是它们可以是随机化算法，而且必须是真随机算法除了特殊情况。

线性时间
如果一个算法的时间复杂度为O(n)，则称这个算法具有线性时间，或O(n)时间。非正式地说，这意味着对于足够大的输入，运行时间增加的大小与输入成线性关系。例如，一个计算列表所有元素的和的程序，需要的时间与列表的长度成正比。这个描述是稍微不准确的，因为运行时间可能显著偏离一个精确的比例，尤其是对于较小的n。

线性对数（准线性）时间
若一个算法时间复杂度T(n) = O(nlog n)，则称这个算法具有线性对数时间。因此，从其表达式我们也可以看到，线性对数时间增长得比线性时间要快，但是对于任何含有n，且n的幂指数大于1的多项式时间来说，线性对数时间却增长得慢。

多项式时间

强多项式时间，弱多项式时间与伪多项式时间

我们先定义一个计算模型，称作算术模型。在算术模型中，数字之间的算术运算（加减乘除、比较大小）可以在单位时间内完成（即 O(1) 时间内完成，与数字大小无关）。

如果一个算法在算术模型下的操作数是输入中的数字个数的多项式，并且空间复杂度是输入规模（而非数字个数）的多项式，则这个算法是 强多项式时间 的。由于算术操作在一般的计算模型下可以在输入规模（即数字大小的对数）的多项式时间内完成，强多项式时间的算法一定是多项式时间的。

一般来说，强多项式时间的算法的时间复杂度与值域无关。

如果一个算法是多项式时间的但不是强多项式时间的，则它是弱多项式时间的，这表明它在图灵机模型下是多项式的，但在算术模型下不是。

例如，计算最大公约数的欧几里得算法，时间复杂度为 O(log a + log b)（a 和 b 为输入的数的大小），是弱多项式时间的。因为它的实际运行时间是关于a,b的长度（位数）的多项式，而不是关于输入中的整数数量的（这个数量总是2）。

如果一个算法的用时是值域的多项式，则称它是伪多项式时间的。伪多项式时间的算法可能是多项式时间的也可能不是，可能不是多项式时间是因为表示一个大小为 n 的正整数一般只需要 O(log n) 个二进制位，所以关于值域多项式时间的算法往往关于输入长度是指数级时间的。虽然从定义上来说伪多项式时间也可能是多项式时间，但当我们说一个算法是伪多项式时间的，一般都是说这个算法不是多项式时间的。

例如，背包问题是 NP-hard 问题，但它有基于动态规划的伪多项式时间的解法。

复杂度类

从多项式时间的概念出发，在计算复杂度理论中可以得到一些复杂度类。以下是一些重要的例子。

 P：包含可以使用确定型图灵机在多项式时间内解决的决定性问题。
 NP：包含可以使用非确定型图灵机在多项式时间内解决的决定性问题。
 ZPP：包含可以使用概率图灵机在多项式时间内零错误解决的决定性问题。
 RP：包含可以使用概率图灵机在多项式时间内解决的决定性问题，但它给出的两种答案中（是或否）只有一种答案是一定正确的，另一种则有几率不正确。
 BPP：包含可以使用概率图灵机在多项式时间内解决的决定性问题，它给出的答案有错误的概率在某个小于0.5的常数之内。
 BQP：包含可以使用量子图灵机在多项式时间内解决的决定性问题，它给出的答案有错误的概率在某个小于0.5的常数之内。

在机器模型可变的情况下，P在确定性机器上是最小的时间复杂度类。例如，将单带图灵机换成多带图灵机可以使算法运行速度以二次阶提升，但所有具有多项式时间的算法依然会以多项式时间运行。一种特定的抽象机器会有自己特定的复杂度类分类。

超越多项式时间

如果一個算法的時間 T(n) 沒有任何多項式上界，則稱這個算法具有超越多項式（superpolynomial）時間。在這種情況下，對於所有常數 c 我們都有 T(n) = ω(nc)，其中 n 是輸入參數，通常是輸入的數據量（比特數）。指數時間顯然屬於超越多項式時間，但是有些算法僅僅是很弱的超越多項式算法。例如，對於 n 比特的輸入需要運行 nO(log log n) 時間；對於足夠大的 n，這時間比任何多項式都快；但是輸入要大得不切實際，時間才能真正超過低階的多項式。

准多项式时间
準多項式時間演算法是運算慢於多項式時間的演算法，但不會像指數時間那麼慢。對一些固定的 ，準多項式時間演算法的最壞情況運行時間是 。如果準多項式時間演算法定義中的常數“c”等於1，則得到多項式時間演算法；如果小於1，則得到一個次線性時間算法。

次指數時間
術語次指數時間用於表示某些演算法的運算時間可能比任何多項式增長得快，但仍明顯小於指數。在這種狀況下，具有次指數時間演算法的問題比那些僅具有指數演算法的問題更容易處理。“次指數”的確切定義並沒有得到普遍的認同，我們列出了以下兩個最廣泛使用的。

第一定义
如果一個問題解決的運算時間的對數值比任何多項式增長得慢，則可以稱其為次指數時間。更準確地說，如果對於每個 ε> 0，存在一個能於時間 O(2nε) 內解決問題的演算法，則該問題為次指數時間。所有這些問題的集合是複雜性SUBEXP，可以按照 DTIME 的方式定義如下。

第二定义
一些作者將次指數時間定義為 2o(n) 的運算時間。該定義允許比次指數時間的第一個定義更多的運算時間。這種次指數時間演算法的一個例子，是用於整數因式分解的最著名古典演算法——普通數域篩選法，其運算時間約為 ，其中輸入的長度為 n。另一個例子是的最著名演算法，其運算時間為 。

指数时间
若T(n) 是以 2poly(n)為上界，其中 poly(n) 是 n 的多項式，則演算法被稱為指數時間。更正規的講法是：若 T(n) 對某些常數 k是由 O(2nk) 所界定，則演算法被稱為指數時間。在確定性圖靈機上認定為指數時間演算法的問題，形成稱為EXP的複雜性級別。

有時侯，指數時間用來指稱具有 T(n) = 2O(n) 的演算法，其中指數最多為 n 的線性函數。這引起複雜性等級 E。

双重指数时间
若 T(n) 是以 22poly(n) 為上界，其中 poly(n) 是 n 的多項式，則演算法被稱為雙重指數時間。這種演算法屬於複雜性等級 2-EXPTIME。

眾所周知的雙重指數時間演算法包括：
 的決策程序
 計算（在最差狀況Mayr,E. & Mayer,A.: The Complexity of the Word Problem for Commutative Semi-groups and
Polynomial Ideals. Adv. in Math. 46(1982) pp. 305-329）
 實封閉體的量詞消去至少耗費雙重指數時間，J.H. Davenport & J. Heintz: Real Quantifier Elimination is Doubly Exponential.
J. Symbolic Comp. 5(1988) pp. 29-35.而且可以在這樣的時間內完成。G.E. Collins: Quantifier Elimination for Real Closed Fields by Cylindrical Algebraic
Decomposition. Proc. 2nd. GI Conference Automata Theory & Formal Languages (Springer Lecture
Notes in Computer Science 33) pp. 134-183

参见
 L符號
博弈复杂度
計算複雜性理論
 零一律
 柯爾莫哥洛夫空間
 柯氏复杂性
 空间复杂度

參考資料

Category:算法分析
Category:計算複雜性理論
Category:计算资源