计算时间复杂度
1.引言
我们之前学过许多算法,例如:二分查找、归并排序(博客链接,若没学过,慢走不送)。
我们在学习二分查找的时候就抛出过一个问题:如何计算时间复杂度。我们当时只是粗略的讲了一下什么是时间复杂度,今天我们来学习计算一下。
2.计算时间复杂度
2.1 认识不同种类时间复杂度
2.1.1 常数阶
即时间复杂度为 的算法。例如:
#include <bits/stdc++.h>
using namespace std;
int main() {cout << "Hello World" << endl; // 运行第一步return 0;
}
但不一定只执行一次,又例如:
#include <bits/stdc++.h>
using namespace std;
int main() {int n; // 运行第一步cin >> n; // 运行第二步cout << n << endl; // 运行第三步return 0;
}
这段代码的时间复杂度也是 O(1),只要没有循环(重复写一段代码也算循环)时间复杂度就是 O(1)。
2.1.2 对数阶
即时间复杂度为 的算法,例如:
#include <bits/stdc++.h>
using namespace std;
int main() {int n; // 执行1次cin >> n; // 执行1次int sum = 1; // 执行1次while(sum < n) // 执行 LogN 次sum *= 2; // 每次执行1次cout << sum << endl; // 执行1次return 0;
}
这里默认是 ,如果是以2为底,那么在 编程 中可以省略,数学中不可以。如果是以别的数字为底,那么需要特殊标注,例如
。
2.1.3 线性阶
即时间复杂度为 的算法,例如:
#include <bits/stdc++.h>
using namespace std;
int main() {int n; // 执行1次cin >> n; // 执行1次for(int i = 1; i <= 10; i++) // 执行 n 次cout << i << " "; // 每次执行1次cout << endl; // 执行1次return 0;
}
我们可以看到,就是一个单纯的循环。
2.1.4 nlogn阶
即时间复杂度为 的算法。例如:
#include <bits/stdc++.h>
using namespace std;
int main() {int n; // 执行1次cin >> n; // 执行1次for(int i = 1; i <= n; i++) // 执行 n 次{int sum = 1; // 每次执行1次while(sum < n) // 每次执行 LogN 次sum *= 2; // 每次执行1次cout << sum << endl; // 每次执行1次}return 0;
}
就是 特别简单。
2.1.5 平方阶
即时间复杂度为 的算法。例如:
#include <bits/stdc++.h>
using namespace std;
int main() {int n; // 执行1次cin >> n; // 执行1次for(int i = 1; i <= n; i++) // 执行 n 次{for(int j = 1; j <= n; j++) // 每次执行 n 次cout << '(' << i << ', ' << j << ')' << ' '; // 每次执行1次cout << endl; // 每次执行1次}return 0;
}
就是 特别简单。
2.1.6 立方阶
即时间复杂度为 的算法。例如:
#include <bits/stdc++.h>
using namespace std;
int main() {int n; // 执行1次cin >> n; // 执行1次for(int i = 1; i <= n; i++) // 执行 n 次{for(int j = 1; j <= n; j++) // 每次执行 n 次{for(int k = 1; k <= n; k++) // 每次执行 n 次cout << '(' << i << ', ' << j << ', ' << ')' << ' '; // 每次执行1次cout << endl; // 每次执行1次}cout << endl; // 每次执行1次}return 0;
}
就是 特别简单。
2.1.7 指数阶
即时间复杂度为 的算法。例如:
#include <bits/stdc++.h>
using namespace std;
int fib(int n) {if(n == 0 || n == 1)return 1; // 执行1次elsereturn fib(n - 1) + fib(n - 2); // 执行 2^n 次
}
int main() {int n; // 执行1次cin >> n; // 执行1次cout << fib(n) << endl;return 0;
}
我们可以看到,斐波那契数列的递归求解时间复杂度就是 O(2^n)。
2.1.8 阶乘阶
即时间复杂度为 的算法。本时间复杂度太大太罕见,暂无代码示例(若实在想看,
慢走不送)
2.2 计算时间复杂度
要计算的代码:
#include <bits/stdc++.h>
using namespace std;
int arr[105];
int search(int target) {int left = 1, right = n;while(left <= right){int mid = left + (right - left) / 2;if(arr[mid] == target)return mid;else if(arr[mid] > target)right = mid - 1;elseleft = mid + 1;}return -1;
}
int main() {int n, target;cin >> n >> target;for(int i = 1; i <= n; i++)cin >> arr[i];sort(arr + 1, arr + n + 1);cout << search(target) << endl;return 0;
}
首先把算法的执行次数写成一个多项式,就是把代码每一个部分写成一个单项式,然后相加得到多项式。
例如上面的代码就是 T(n) = 3 + n + LogN。
然后只保留最高阶项,若没有,就找出带有未知量的,就是LogN。
然后在去掉前面的系数,若没有,就不变。
然后把剩下的部分放到大O表示法的括号里面,完成!时间复杂度为:
3.总结
这就是我们今天学习的内容,内容比较多,希望大家好好消化。
再见!