时间复杂度
什么是时间复杂度
在编程和计算机科学中,时间复杂度是一种衡量算法运行时间如何随着输入大小变化的方式。它帮助我们理解算法在最坏情况下的运行时间。时间复杂度通常用大O表示法表示。
换句话说,大O就是用来表示算法运行时间的上界
下面是一些常见的时间复杂度:
时间复杂度 | 名称 | 代表 |
---|---|---|
O(1) | 常数时间复杂度 | 无论输入大小如何,该算法的运行时间都保持恒定。例如,查找数组中的第一个元素 |
O(n) | 线性时间复杂度 | 算法的运行时间与输入大小成正比。例如,遍历数组中的所有元素 |
O(n^2) | 二次时间复杂度 | 当输入大小翻倍时,该算法的运行时间会大致增加四倍。常见的例子是冒泡排序算法 |
O(log n) | 对数时间复杂度 | 当输入大小翻倍时,需要的额外运行时间是常数。例如,二分查找 |
O(n log n) | 线性对数时间复杂度 | 算法的运行时间与输入大小的对数成正比。如快速排序和归并排序等 |
O(2^n) | 指数时间复杂度 | 运行时间随输入大小指数级增长。如递归计算斐波那契数列 |
如何判定某一个程序的时间复杂度
基本步骤
在计算一个程序的时间复杂度时,主要关注的是随着输入大小的增加,程序执行操作数量的增长情况。以下是一些**基本的步骤**:
1.首先,你需要理解程序如何运行。这通常意味着你需要阅读和理解代码。你需要知道循环、递归、条件语句等如何影响算法的运行。你需要查看代码中的每一行,看看它们都执行了些什么操作,这些操作会如何随着输入的规模变化而变化。
(开始估计时间复杂度的一种常见方法是查看最内层循环中的每一行代码。分析这部分代码的运行时间与输入大小的关系。通常可以将一次加法、乘法运算,一次比较,一次赋值,或者一次访问数组元素的操作都当作是常数时间操作。)
2.其次,你需要看看程序中有没有循环。如果有,循环次数通常会影响时间复杂度。例如,对一个n元素的数组进行遍历常常会带来O(n)的时间复杂度。如果一个循环在另一个循环中,那就可能是O(n^2),以此类推。
3.接着,检查递归。递归函数的时间复杂度分析可能会涉及到递推关系,需要结合递归树或者主定理来计算。
4.然后,如果你的算法中包含了调用其他复杂算法或者数据结构,比如排序函数或者哈希表等,你需要知道他们的时间复杂度并考虑在内。
5.最后,将所有的部分结合起来。总的时间复杂度是由最大的部分决定,所以我们只需要保留最大的项,去掉所有低阶项和高阶项的常数系数,这就是大O表示法的来源。
举个栗子🌰
现在有一个这样的代码:
#include<bits/stdc++.h>
using namespace std;
int main()
{
long long n;
long long k = 0;
cin >> n;
for(long long i=1;i<=n;i++)
{
k++;
}
cout << k;
}
上述代码有一次循环,所以该程序时间复杂度就是O(n)
接下来又有一个代码:
#include<bits/stdc++.h>
using namespace std;
int main()
{
long long n;
long long k = 0;
cin >> n;
for(long long i = 1; i <= n; i++)
{
for(long long j = 1; j <= n; j++)
{
k++;
}
}
cout << k;
}
上述代码有一次循环,这一次循环里面还有一次循环。所以该程序时间复杂度就是O(n^2)
我们可以用下面的程序来测试程序的时间复杂度:👨🏻💻
#include<bits/stdc++.h>
using namespace std;
using namespace chrono;
// O(n)
void lizi1(long long n) {
long long k = 0;
for (long long i = 0; i < n; i++) {
k++;
}
}
// O(n^2)
void lizi2(long long n) {
long long k = 0;
for (long long i = 0; i < n; i++) {
for (long j = 0; j < n; j++) {
k++;
}
}
}
// O(nlogn)
void lizi3(long long n) {
long long k = 0;
for (long long i = 0; i < n; i++) {
for (long long j = 1; j < n; j = j*2) {
k++;
}
}
}
int main()
{
long long n;
while(1)
{
cout << "输入n:" << endl;
cin >> n;
milliseconds start_time = duration_cast<milliseconds>(system_clock::now().time_since_epoch());
lizi1(n);//函数切换
milliseconds end_time = duration_cast<milliseconds>(system_clock::now().time_since_epoch());
cout << "运行时间:" << milliseconds(end_time).count() - milliseconds(start_time).count() << "ms" << endl;
}
}