算法基础--算法的时间复杂度和空间复杂度

1.算法效率

时间复杂度主要衡量一个算法的运行快慢,而空间复杂度主要衡量一个算法运行所需的额外空间。

2.时间复杂度

2.1时间复杂度概念

算法的时间复杂度是一个函数,定量描述了该算法的运行时间。一个算法执行所耗费的时间,从理论上讲是不能算出来的,只能程序跑出来才知道,这很麻烦,所以有了时间复杂度的分析方式。一个算法所花费的时间与其语句执行次数成正比,算法中的基本操作次数为算法的时间复杂度。

实际中我们计算时间复杂度并不一定计算精确执行次数,只需要大概执行次数,用大O的渐进法估算。

2.2大O的渐进表示法

大O:用于描述函数渐进行为的数学符号。

推导方法:

1.用常数1取代所有加法常数。

2.再修改之后的运行次数函数中只保留最高阶项

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

实例1:

计算fun1的时间复杂度?

void fun1(int n)
{
    int count = 0;
    for(int i=0;i<2*n;i++)
    {
         ++count;
     }
   
    int m = 10;
    while(m--)
    {
        ++count;
    }
}

此例时间复杂度O(N)

精确算法:2N+10 。常数对此影响不大,计算时间复杂度最高阶项系数为2,则去除常数。其时间复杂度为O(N)

实例2:计算fun2时间复杂度?

void fun2(int N,int M)
{
    int count = 0;
    for(int i=0;i<M;i++)
    {
         ++count;
     }
   
    for(int i = 0;i<N;++k)
    {
        ++count;
    }
}
时间复杂度为O(M+N)

【拓】

此时若有条件:

M >> N,时间复杂度为O(M);

N >> M,时间复杂度为O(N);

M与N差不多大,时间复杂度为O(M+N)。

实例3:计算fun3时间复杂度?

void fun3(int n)
{
    int count = 0;
    for(int i=0;i<100;i++)
    {
         ++count;
     }
   
}
时间复杂度为O(1)

时间复杂度为O(1),表示代表1次,是常数次。

实例4:计算strchr的时间复杂度?

const char * strchr (const char * str,int character);

另外一些算法的时间复杂度存在不同情况:

最坏情况:上界;

平均情况:期望次数(平均次数);

最好:下界。

例如:在一个长度为N的数组搜索一个数据x

最好情况:1次找到。

最差情况:N次找到。

平均情况:N/2次找到。

在实际中当一个算法随着输入不同,时间复杂度不同,一般情况关注的是算法的最坏运行情况,所以数组中搜索数据时间复杂度为O(N)。(例外,希尔排序很少出现最坏情况,我们以平均情况计算)

实例5:计算Bubblesort时间复杂度?

void Bubblesort(int * a,int n)
{
    assert(a);
    for(size_t end = n;end > 0;--end)
    {
        int exchange = 0;
        for(size_t i = 1;i < end;++i)
        {
            if(a[i-1]>a[i])
            {
                Swap(&a[i-1],&a[i]);
                exchange = 1;
             }
        }
    
         if(exchange == 0)
             break;
     }
}
精确:F(N)= (N-1)+(N-2)+...+1 = N*(N-1)/2
时间复杂度O(N^2)

实例6:计算二分查找的时间复杂度?

int BinarySearch(int* a,int n,int x)
{
    asssert(a);

    int begin = 0;
    int end = n;
    while(begin < end)
    {
        int mid = begin + ((end-begin)>>1);
        if(a[mid] < x)
            begin = mid+1;
        else if(a[mid]>x)
             end = mid;
        else
             return mid;
     }

    return -1;
}

假设查找了x次
1*2*2*2...=n
2^x=n
时间复杂度O(log2 N)

实例7:计算阶乘递归Fac的时间复杂度?

//计算阶乘递归时间复杂度?
long long Fac(size_t N)
{
    if(0==N)
        return 1;

    return Fac(N-1)*N ;
}

时间复杂度O(N)

//计算斐波那契递归时间复杂度?
long long Fib(size_t N)
{
  if(N<3)
     return 1;

  return Fib(N-1)+Fib(N-2);
}

右边一些递归分支会提前结束,缺x次
精确:Fib(N) = 2^0+2^1+2^2+...+2^(N-1)-X ,x远小于2^N可忽略
时间复杂度:O(2^N)

递归算法:递归次数*每次递归调用的次数

3.空间复杂度

空间复杂度也是数学函数表达式,是对一个算法在运行过程中临时额外占用存储空间大小的量度。

空间复杂度不是程序占用了多少byte的空间,因为没有意义,所以空间复杂度算的是变量的个数。空间复杂度计算规则跟时间复杂度类似

注意:函数运行时所需要的栈空间(存储参数、局部变量、一些寄存器信息等)在编译期间已经确定好了,因此空间复杂度主要通过函数运行时显式申请的额外空间来确定

实例1:计算Bubblesort空间复杂度?

void Bubblesort(int * a,int n)
{
    assert(a);
    for(size_t end = n;end > 0;--end)
    {
        int exchange = 0;
        for(size_t i = 1;i < end;++i)
        {
            if(a[i-1]>a[i])
            {
                Swap(&a[i-1],&a[i]);
                exchange = 1;
             }
        }
    
         if(exchange == 0)
             break;
     }
}
额外使用了end、i和exchange这三个空间
空间复杂度O(1)

实例2:计算递归的空间复杂度?

//计算阶乘递归空间复杂度?
long long Fac(size_t N)
{
    if(0==N)
        return 1;

    return Fac(N-1)*N ;
}

空间复杂度O(N)

//计算斐波那契递归时间复杂度?
long long Fib(size_t N)
{
  if(N<3)
     return 1;

  return Fib(N-1)+Fib(N-2);
}


空间复杂度:O(N)

  • 13
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值