算法时间复杂度
算法运行时间
一个算法的运行时间是指一个算法在计算机上运行所耗费的时间,大致可以等于计算机执行一种简单的操作(赋值、比较、移动等)所需要的时间与算法中进行该简单操作次数的乘积。
算法运行时间
=
一个简单操作所需的时间
×
简单操作的次数
算法运行时间=一个简单操作所需的时间\times简单操作的次数
算法运行时间=一个简单操作所需的时间×简单操作的次数
也就是算法中每条语句的执行时间之和(一种简单操作对应一条语句)
算法运行时间
=
∑
(
一条语句的执行次数
×
该语句执行一次所需的时间
)
算法运行时间=\sum{(一条语句的执行次数\times该语句执行一次所需的时间)}
算法运行时间=∑(一条语句的执行次数×该语句执行一次所需的时间)
每条语句执行一次所需的时间,一般是随机器而异的。取决于机器的指令性能、速度以及编译的代码质量。是由机器本身的软硬件环境决定的,这与算法本身无关。
所以,我们可以假设执行每条语句所需的时间均为单位时间。此时对算法运行时间的讨论就可转化为讨论该算法中所有语句的执行次数。
例:两个 n × n n{\times}n n×n矩阵相乘的算法
for (i = 1; i <= n; i++) \\语句一
{
for (j = 1; j <= n; j++) \\语句二
{
c[i][j] = 0; \\语句三
for (k = 1; k <= n; k++) \\语句四
{
c[i][j] = c[i][j] + a[i][k] * b[k][j]; \\语句五
}
}
}
语句一的操作是判断,执行次数是 n + 1 次( i = n 之后还会再执行一次 ++ 操作,再进行一次判断,所以是 n + 1 次)
语句二的操作是判断,执行次数是 n * ( n + 1 ), n 是因为语句一只执行了 n 次,乘是因为这是嵌套循环, n + 1 理由同上
语句三的操作是赋值,执行次数是 n * n
语句四的操作是判断,执行次数是n * n * ( n + 1 )
语句五的操作是赋值,执行次数是n * n * n
所以上述算法的运行时间
T
(
n
)
T(n)
T(n)为
T
(
n
)
=
(
n
+
1
)
+
[
n
×
(
n
+
1
)
]
+
(
n
×
n
)
+
[
n
×
n
×
(
n
+
1
)
]
+
(
n
×
n
×
n
)
=
2
n
3
+
3
n
2
+
2
n
+
1
\begin{align} T(n)&=(n+1)+[n \times (n+1)]+(n \times n)+[n \times n \times (n+1)]+(n \times n \times n)\\ \ &=2n^3 + 3n^2 + 2n + 1 \end{align}
T(n) =(n+1)+[n×(n+1)]+(n×n)+[n×n×(n+1)]+(n×n×n)=2n3+3n2+2n+1
时间复杂度
为了便于比较不同算法的时间效率,我们仅比较它们(算法运行时间)的数量级。
若有某个辅助函数 f ( n ) f(n) f(n),使得当 n 趋近于无穷大时, T ( n ) f ( n ) \frac{T(n)}{f(n)} f(n)T(n)的极限值为不等于零的常数,则称 f ( n ) f(n) f(n)是 T ( n ) T(n) T(n)的同数量级函数。记作 T ( n ) = O ( f ( n ) ) T(n) = O(f(n)) T(n)=O(f(n)),称 O ( f ( n ) ) O(f(n)) O(f(n))为算法的渐进时间复杂度( O O O是数量级的符号),简称时间复杂度。
上面这段话看不懂也没关系,我也看不懂,想要深入了解可以看
https://www.hello-algo.com/chapter_computational_complexity/performance_evaluation/
在这里,我想引用该书中的一句话来帮助理解算法的时间复杂度。
时间复杂度分析统计的不是算法运行时间,而是算法运行时间随着数据量变大时的增长趋势。
在矩阵相乘的例子中,算法的时间复杂度我们可以写成
T
(
n
)
=
O
(
n
3
)
T(n) = O(n^3)
T(n)=O(n3)
简单来说,就是保留最高次幂项,然后去掉其系数
不同的时间复杂度
在数组arr中查找值等于e的元素,返回其所在位置
for (i = 0; i < n; i++)
{
if (arr[i] == e)
{
return i + 1;
}
}
最好情况:比较 1 次
最坏情况:比较 n 次
最坏时间复杂度:指在最坏情况下,算法的时间复杂度
平均时间复杂度:指在所有可能输入实例在等概率出现的情况下,算法的期望运行时间
最好时间复杂度:指在最好情况下,算法的时间复杂度
一般总是考虑在最坏情况下的时间复杂度 O ( f ( n ) ) O(f(n)) O(f(n)) ,以保证算法的运行时间不会比它更长。
该例中算法的时间复杂度即为 O ( n ) O(n) O(n)
常见的时间复杂度类型
按从低到高排序
O
(
1
)
<
O
(
log
n
)
<
O
(
n
)
<
O
(
n
log
n
)
<
O
(
n
2
)
<
O
(
2
n
)
<
O
(
n
!
)
常数阶
<
对数阶
<
线性阶
<
线性对数阶
<
平方阶
<
指数阶
<
阶乘阶
O(1)<O(\log{n})<O(n)<O(n\log{n})<O(n^2)<O(2^n)<O(n!)\\ 常数阶<对数阶<线性阶<线性对数阶<平方阶<指数阶<阶乘阶
O(1)<O(logn)<O(n)<O(nlogn)<O(n2)<O(2n)<O(n!)常数阶<对数阶<线性阶<线性对数阶<平方阶<指数阶<阶乘阶
这里的
log
n
\log{n}
logn 一般指以2为底的 n 的对数
log
2
n
\log_2{n}
log2n