之前我们讨论了渐进分析,最佳最坏平均情况的分析以及渐进符号。在这一篇中我们分析一下迭代的简单程序。
1. O(1):
如果程序中没有包含任何的循环,递归或者任何的非常数时间的函数,我们就说这个程序的时间复杂度为O(1)。例如简单的swap()函数就是O(1)
// Here c is a constant
for (int i = ; i <= c; i++) {
// some O(1) expressions
}
这个程序也是O(1)因为C是常数。所以整个程序可以再常数时间内完成。
2.O(n):
如果循环计数器用一个常数来减少或增加。那我们就说这个循环的时间复杂度是O(n)
// Here c is a positive integer constant
for (int i = ; i <= n; i += c) {
// some O(1) expressions
} for (int i = n; i > ; i -= c) {
// some O(1) expressions
}
(如果C=1,每个for loop要运行n次O(1) expressions)
3.O(nc):
嵌套循环的时间复杂度等于最里面的程序的运行次数。
for (int i = ; i <=n; i += c) {
for (int j = ; j <=n; j += c) {
// some O(1) expressions
}
} for (int i = n; i > ; i += c) {
for (int j = i+; j <=n; j += c) {
// some O(1) expressions
}
这两个嵌套循环的时间复杂度都是O(n2).选择排序和插入排序的时间复杂度都是O(n2)。
4.O(logN):
如果循环计数器乘以或除以一个常数来减少或增加。那我们就说这个循环的时间复杂度是O(logn)
for (int i = ; i <=n; i *= c) {
// some O(1) expressions
}
for (int i = n; i > ; i /= c) {
// some O(1) expressions
}
二分查找就是O(logn) 的时间复杂度。
5.O(loglogn)
如果循环计数器用一个指数来减少或增加。那我们就说这个循环的时间复杂度是O(loglogn)
// Here c is a constant greater than 1
for (int i = ; i <=n; i = pow(i, c)) {
// some O(1) expressions
}
//Here fun is sqrt or cuberoot or any other constant root
for (int i = n; i > ; i = fun(i)) {
// some O(1) expressions
}
如何求一些循环组合的时间复杂度?
当出现一些连续的循环时,我们通过把每一个循环的时间复杂度加到一起来求总体的时间复杂度。
for (int i = ; i <=m; i += c) {
// some O(1) expressions
}
for (int i = ; i <=n; i += c) {
// some O(1) expressions
}
Time complexity of above code is O(m) + O(n) which is O(m+n)
If m == n, the time complexity becomes O(2n) which is O(n).
当循环中有很多if else 的语句时,怎么计算时间复杂度?
我们之前讨论过,最坏的时间复杂度才是最有用的信息。所以我们要考虑最坏的情况,也是就if-else的条件下,最多的语句会执行。例如线性搜索,我们会主要考虑要找的元素在最后一个或者不在数组中。(这样就会执行最多次数的语句)
如果程序有太多的if-else 语句,我们可以通过忽略if - else 语句或者其他的复杂句子来找到上限。
原文链接:
http://www.geeksforgeeks.org/analysis-of-algorithms-set-4-analysis-of-loops/
翻译:
Rui