对算法复杂度的浅层讨论

斐波那契数列引发的思考

第一种写法:

#include<bits/stdc++.h>
using namespace std;
int fibs(int n) {
    if(n<=1) return 1;
    else return fibs(n-1)+fibs(n-2);
}
int main()
{
    int n;
    cin>>n;
    cout<<fibs(n)<<endl;
    return 0;
}

第二种写法:

#include<bits/stdc++.h>
using namespace std;
int fibs(int n) {
    int first=0;
    int second=1;
    for(int i=0;i<n-1;i++) {
        int sum=first+second;
        first=second;
        second=sum;
    }
    return second;
}

当我们输入1,5,28,45等这些数时发现,两种方法均可瞬间得出我们想要的结果,但当我们输入的数为64时,会出现一个问题:方法一迟迟得不出结果,而方法二却是瞬间得出来结果。why?

如何评价一个算法的好坏?

如果单从执行效率上进行评估,可能会想到这么一种方案:比较不同算法对同一组输入的执行处理时间 (事后统计法)

上述方案有比较明显的缺点

  • 执行时间严重依赖硬件以及运行时各种不确定的环境
  • 必须编写相应的测算代码
  • 测试数据的选择比较难保证公正性

一般从以下维度来评估算法的优劣

  • 正确性、可读性、健壮性(对不合理输入的反应能力)
  • 时间复杂度(time complexity):估算程序指令的执行次数(执行时间)
  • 空间复杂度(space complexity):估算所需占用的内存空间

时间复杂度的估算

//执行次数为1
int f(int n) {
    if(n>10) cout<<"n>10"<<endl;
    else if(n>5) cout<<"n>5"<<endl;
    else cout<<"n<=5"<<endl;
}
//执行次数为1+4+4+4=13
for(int i=0;i<4;i++) {
    cout<<"test"<<endl;
}
//执行次数为1+n+n+n=3n+1;
for(int i=0;i<n;i++) {
    cout<<"test"<<endl;
}
//执行次数为1+n+n+n*(1+3n)=3n^2+3n+1
for(int i=0;i<n;i++){
    for(int j=0;j<n;j++) {
        cout<<"test"<<endl;
    }
}
//执行次数为1+n+n+n*(1+15*3)=48n+1
for(int i-0;i<n;i++) {
    for(int j=0;j<15;j++) {
        cout<<"test"<<endl;
    }
}
//执行次数为log2(n)
while(n=n/2) {
    cout<<"test"<<endl;
}
//执行次数为1+log2(n)+log2(n)+log2(n)*(1+3n)=1+3*log2(n)+2*nlog2(n)
for(int i=0;i<n;i+=i) {
    for(int j=0;j<n;j++) {
        cout<<"test"<<endl;
    }
}
/*i+=i即为i=i*2*/

大O表示法(Big O)

  • 一般用大O表示法来描述复杂度,它表示的数据规模n对应的复杂度
  • 忽略常数、系数、低阶
  1. 9——O(1)
  2. 2n+3——O(n)
  3. n^2 +2n+6——O(n^2)
  4. 4n^2+ 3n^2+ 22n+100——O(n^3)

在这里插入图片描述

对数阶的细节

对数阶一般省略底数
log2(n)=log2(9)*log9(n)

所以log2(n)、log9(n)统称为logn

所以根据大O表示法上面的程序的算法复杂度可以表示为
O(1)、O(1)、O(n)、O(n^2)、O(n)、O(logn)、O(nlog2(n))

对斐波那契数复杂度的分析

#include<bits/stdc++.h>
using namespace std;
int fibs(int n) {
    if(n<=1) return 1;
    else return fibs(n-1)+fibs(n-2);
}
int main()
{
    int n;
    cin>>n;
    cout<<fibs(n)<<endl;
    return 0;
}

假如输入的是5,则可得如下图解
在这里插入图片描述

1+2+4+8=2^0 +2^1 +2^2 +2^3 =2^4 -1=2^(n-1)-1 =0.5*2^n -1

所以复杂度为O(2^n)

在这里插入图片描述

算法的优化方向

  • 用尽量少的储存空间
  • 用尽量少的执行步骤(执行时间)
  • 根据情况,可以
  1. 空间换时间(字符串哈希)
  2. 时间换空间
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

无所畏惧的man

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值