它表示随着问题规模 n 的增大,算法执行时间的增长率和 f(n) 的增长率相同,称作
算法的 渐近时间复杂度 (asymptotic time complexity) ,简称
时间复杂度。
显然,被称作问题的基本操作的原操作应该是其重复执行次数和算法的执行时间成正比的原操作,在多数情况下,它是最深层循环内的语句中的原操作,它的执行次数和包含它的语句的频度相同。语句的
频度 (frequency count) 指的是该语句重复执行的次数,例如,在下列 3 个程序段中:
(a) { ++x; s = 0; }
(b) for (i = 1; i <= n; ++i) {++x; s += x; }
(c) for (j = 1; j <= n; ++j )
for (k = 1; k <= n; ++k) { ++x; s += x)}
这里,3 个程序段中含有 "x 增 1“ 的语句的频度分别为 1, n 和 n[sup]2[/sup] ,则这 3 个程序段的时间复杂度分别为 O(1) , O(n) O(n[sup]2[/sup]) ,分别称为
常量阶、
线性阶和
平方阶。算法还可能呈现的时间复杂度有对数阶 O(log n) , 指数阶 O(2[sup]n[/sup]) 等。不同数量级事件安复杂度的性状如下图所示:

由图中可见,我们应该尽可能选用多项式 O(n[sup]2[/sup]) 的算法,而不希望用指数阶的算法。
一般情况下,对一个问题(或一类算法)只需选择一种基本操作来讨论算法的时间复杂度即可,有时也需要同时考虑几种基本操作,甚至可以对不同的操作赋予不同的权值,以反应不同操作所需的相对时间,这种做法便于综合比较解决同一问题的两种完全不同的算法。
由于算法的时间复杂度考虑的只是对于问题规模 n 的增长率,则在难以精确计算基本操作执行次数(或语句频度)的情况下,只需求出它关于 n 的增长率或阶即可。例如,在下列程序段中:
for (i = 2; i <= n; ++i)
for (j = 2; j <= i -1; ++j) {++x; a[j] = x;}
语句 ++x 的执行次数关于 n 的增长率为 n[sup]2[/sup] ,它是语句频度表达式 (n-1)(n-2)/2 中增长的项。
从两个 for 循环可以看到,当 i = 3 时,第 2 个 for 循环中的语句才可以得到执行,也就是说从 n - 2 开始第 2 个 for 开始得到执行。那么在第 2 个 for 中就有:
i = 3 时,循环体执行 1 次
i = 4 时,循环体执行 2 次
....
总共的循环次数就是 1 + 2 + 3 + ... + (n - 2) ,这个数列一共有 (n - 2) 项这样数列的和为:
( (1 + (n - 2) ) x (n - 2) ) / 2 ,即为 (n-1)(n-2)/2 |