3.4 时间复杂度与空间复杂度

1.时间复杂度的概念

算法的时间复杂度是一个函数(指的是数学函数),算法中的基本操作的执行次数,为算法的时间复杂度。

#include<iostream>
using namespace std;
//时间复杂度:
int main(){
    int count=0;
    for (int i=0;i<N;i++){
        for (int j=0;j<N;j++){
            count++;
        }
    }
    //N*N
    for(int k=0;k<2*N;k++){
        count++;
    }
    //2*N
    int M=10;
    while(M--){
        count++;
    }
    //M=10
    cout<<count<<endl;
    return 0;
    }

(1)时间复杂度表达式为:F(N) = N*N+2 * N + 10

(2)大O渐进表示法:O(N^2)

这个函数的基本操作次数是:F(N) = N*N+2 * N + 10,随着N的增大,后两项对整个影响的结果变可以忽略不计小。当N无限大的时候,后两项对结果的影响不计。

实际中我们计算时间复杂度时,我们其实并不一定要计算精确的执行次数,而只需要大概执行次数,那么这里我们使用大 O的渐进表示法。

2.大O的渐进表示法

大 O 符号( Big O notation ):是用于描述函数渐进行为的数学符号。

推导大 O 阶方法:

(1 、用常数 1 取代运行时间中的所有加法常数。

(2 、在修改后的运行次数函数中,只保留最高阶项。

(3 、如果最高阶项存在且不是 1 ,则去除与这个项目相乘的常数。得到的结果就是大 O 阶。

(4 、另外有些算法的时间复杂度存在最好、平均和最坏情况:最坏情况:任意输入规模的最大运行次数(上界) ;平均情况:任意输入规模的期望运行次数 ;最好情况:任意输入规模的最小运行次数(下界);在实际中一般情况关注的是算法的最坏运行情况,所以数组中搜索数据时间复杂度为O(N)

3.常见的时间复杂度的计算:

代码一:

int count=0;
for (int k=0; k<100; k++){
    count++;
}
cout<<count;

时间复杂度为O(1)【因为大O的渐进表示法的第一条用常数1取代运行时间中的所有加法常数。】(我们可以看到执行次数为100)(所以,看到大O的渐进表示法,并不是让我们只能执行一次)(常数都是1)

代码二:

int count=0;
for(int k=0;k<2*N;k++){
    count++;
}
int M=10;
while(M--){
    count++;
}
cout<<count;

时间复杂度为O(N)[大O的渐进表示法,第三条:如果最高阶项存在且不是1,则去除与这个项目相乘的常数。得到的结果就是大O阶。【实际的执行次数是:2*N+10】

代码三:

int count=0;
for (int k=0; k<M;k++){
    count++;
}
for (int k=0;k<N;k++){
    count++;
}
cout<<count;

时间复杂度为O(N+M);如果给出N远大于M,就可以写成O(N);如果给出N和M差不多就可以写成O(N)或者O(M);该代码什么都没有给,所以就是O(M+N);

代码四:

while (*str){
    if (*str==character)
        return str;
    else
        str++;
}

时间复杂度为O(N);因为不确定什么时候被找到,第四条:在实际中一般情况关注的是算法的最坏运行情况,所以数组中搜索数据时间复杂度为O(N)

关于时间复杂度,我们要准确分析时间复杂度,一定要去看思想,不能仅仅去看程序是几层循环,主要是要看代码的思想。比如:冒泡排序(O(N^2)),就是N-1,N-2,N-3……2,1,是一个等差数列(N-1+1)(N-1)/2=N(N-1)【这是最差情况】,N-1【最好的情况】。

二分查找的时间复杂度:O(㏒₂N )【最好的情况:O(1)一次找到; 最差的情况(找不到的情况):O(log2 N ) (1*2*2*2…2)^X(次)= N(从找不到的时候,向前思想】

时间复杂度,会把O(㏒₂N)简写成O(logN).有些书籍也会写成O(lgN)(这个是不正规的)

代码五:

long long Fac(size_t N){//阶乘
    if (0==N)
        return 1;
    return Fac(N - 1) * N;
}

时间复杂度为O(N);实际上是N+1

代码六:

long long Fac(size_t N){
    if (0==N)
        return 1;
    for (size_t i=0;i<N;i++){
        cout<<i;
    }
    cout<<endl;
    return Fac(N - 1)*N;
}

时间复杂度为O(N^2),;实际上是(N-1)+(N-2)+……+1+0

递归算法的时间复杂度:(1、每次函数调用如果是是O(1),那么就看他的递归次数(递归次数是多少,时间复杂度就是多少)(代码5)

(2、如果不是O(1),那么就看他的递归调用次数的累加(每次递归,函数调用的累加)

代码7

long long Fib(size_t N){
    if(N<3)
        return 1;
    return Fib(N-1) + Fib(N-2);
}

//斐波那契数列

//符合递归算法的第一种

时间复杂度为O(2^N),第一层调用一次,第二层 调用2次,第三层调用4次 ,一直到Fib(3)分成Fib(2)+Fib(1),那就是N-1层(假设每一层都是满的,起始并不是每一层都是满的),那最后一层就是2^(N-1),然后就是等比数列相加,就是(2^n-1)-1

posted @ 2025-05-23 20:14  爱吃泡面的皮卡  阅读(9)  评论(0)    收藏  举报