什么是时间复杂度:
我们先来从实际的函数中来分析:
int example1(int n) {
cout<<"喵喵喵喵喵"<<endl;
}
在上面的函数中,无论输入的数字是多少,函数只会执行一条命令:
cout<<"喵喵喵喵喵"<<endl;
我们设T(n)是在输入数据为n时该段代码的总执行数量,上述example1满足T(n) = 1
int example2( int n) {
int sum = 0;//执行一次命令
//在下面的循环中 将i初始化会执行一次
//将i的值和n比较会执行n+1次
//i++操作会执行n次
for (int i = 0; i<n;i++)
{
sum = sum + i ;
}
return sum;//执行1次
}
在上述函数中一共会执行3n+4次命令,即T(n) = 3n + 4
由于在考虑一个算法的效率时,我们需要考虑的是极端情况,所以我们会对上述T()取极限处理,同时忽略常数的系数,从而对于时间复杂度的计算我们将只考虑T(n)的最高次项,即上述T(n)分别简化为1和3n。因为时间复杂度描述的是增长趋势,所以常数项系数并不重要。在舍去常数系数后,我们将得到上述两个的时间复杂度分别为O(1)和O(n)
大O表示法
大O表示法用于描述算法再最坏情况下的上界,这个最坏情况的理解就是函数最多可能执行的循环次数。
void example(int n) {
for (int i = 0; i < n; i++) {
if (i == 0) {
for (int j = 0; j < n; j++) {
for (int k = 0; k < n; k++) {
cout << j * k << endl;
}
}
}
}
}
如上面所示,上面函数的总执行次数为:
从内层到外层依次数:n^2+n^2+(n^2+n)+n+n+(n+1)+1+1+n+(n+1)+1=3*n^2+6n+5
如何理解上界:该时间复杂度可以表示为O(n^2),可以表示为O(n^3)但是不能表示为O(n)
如何计算常见的时间复杂度
将分为单层循环和多层循环进行分析:
单层循环
void example3(int n)
{
int i = n;
int count = 0 ;
while(i != 1)
{
i = i/2;
count++;
}
cout<<count;
}
解题步骤:
1. 首先列出循环次数t和对应的每一次循环的i值
t | i |
0 | n |
1 | n/2 |
2 | n/4 |
2. 然后列出i与t的关系式
3.根据循环停止条件解方程
求得:
所以上述函数的时间复杂度是 O(log2(n))
多层循环:
void example4(int n) {
for (int i = 1; i <= n; i++) { // 第一层循环
for (int j = 1; j <= i; j++) { // 第二层循环
for (int k = 1; k <= j; k++) { // 第三层循环
}
}
}
}
解题思路:
逐层求和:
最内层:循环执行j次
第二层:
我们忽略常数项系数得到循环执行i^2次
第三层:
我们忽略常数项系数得到循环执行n^3次
最终求出函数时间复杂度为O(n^3)
OK,时间复杂度的学习就到这,谢谢大家!
参考: