计算时间复杂度

1.引言

我们之前学过许多算法,例如:二分查找归并排序(博客链接,若没学过,慢走不送)。

我们在学习二分查找的时候就抛出过一个问题:如何计算时间复杂度。我们当时只是粗略的讲了一下什么是时间复杂度,今天我们来学习计算一下。

2.计算时间复杂度

2.1 认识不同种类时间复杂度

2.1.1 常数阶

即时间复杂度为 的算法。例如:

cpp 复制代码
#include <bits/stdc++.h>
using namespace std;
int main() {
    cout << "Hello World" << endl; // 运行第一步
    return 0;
}

但不一定只执行一次,又例如:

cpp 复制代码
#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 对数阶

即时间复杂度为 ******的算法,例如:

cpp 复制代码
#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 线性阶

即时间复杂度为 的算法,例如:

cpp 复制代码
#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阶

即时间复杂度为 的算法。例如:

cpp 复制代码
#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 平方阶

即时间复杂度为 的算法。例如:

cpp 复制代码
#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 立方阶

即时间复杂度为 的算法。例如:

cpp 复制代码
#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 指数阶

即时间复杂度为 的算法。例如:

cpp 复制代码
#include <bits/stdc++.h>
using namespace std;
int fib(int n) {
    if(n == 0 || n == 1)
        return 1; // 执行1次
    else
        return 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 计算时间复杂度

要计算的代码:

cpp 复制代码
#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;
        else
            left = 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.总结

这就是我们今天学习的内容,内容比较多,希望大家好好消化。

再见!

相关推荐
风暴之零3 分钟前
变点检测算法PELT
算法
深鱼~3 分钟前
视觉算法性能翻倍:ops-cv经典算子的昇腾适配指南
算法·cann
李斯啦果4 分钟前
【PTA】L1-019 谁先倒
数据结构·算法
MSTcheng.4 分钟前
【C++】C++11新特性(二)
java·开发语言·c++·c++11
愚者游世6 分钟前
Delegating Constructor(委托构造函数)各版本异同
开发语言·c++·程序人生·面试·改行学it
小镇敲码人8 分钟前
探索华为CANN框架中的ACL仓库
c++·python·华为·acl·cann
梵刹古音9 分钟前
【C语言】 指针基础与定义
c语言·开发语言·算法
啊阿狸不会拉杆26 分钟前
《机器学习导论》第 5 章-多元方法
人工智能·python·算法·机器学习·numpy·matplotlib·多元方法
liu****42 分钟前
2.深入浅出理解虚拟化与容器化(含Docker实操全解析)
运维·c++·docker·容器·虚拟化技术
A9better1 小时前
C++——不一样的I/O工具与名称空间
开发语言·c++·学习