【算法】算法的时间复杂度和空间复杂度

怎甘沉沦 提交于 2020-02-13 22:27:10

目录结构:

contents structure [-]

 

算法的时间复杂度就是估计一个算法所需的时间,算法的空间复杂度就是估计一个算法所需的内存。算法可以以空间换取时间,也可以以时间换空间。比如,需要求出当前年份是否为闰年,可以写个算法进行计算;也可以预先就把近100年的闰年情况加载到内存中,如果是闰年则为1否则为0,这就是以空间换取时间的栗子。通常情况下“复杂度”都是指的是“时间复杂度”,因此在这篇文章中,笔者也重点介绍时间复杂度。

1.时间复杂度的定义

时间复杂度:在进行算法分析时,语句总的执行次数T(n)是关于问题规模n的函数,进而分析T(n)随n的变化情况并确定T(n)的数量级。算法的时间复杂度,也就是算法的时间量度,记做T(n)=O(f(n)),它表示随问题规模n的增大,算法执行时间的增长率和f(n)的增长率相同,称为算法的渐进时间复杂度,简称为时间复杂度。可以将算法的时间复杂度理解循环次数。

利用大写O()来体现算法时间复杂度的计法,称为大O计法。

最优算法:一般情况下,随着输入规模n的增大,T(n)增长最慢的算法为最优。

2.推导大O阶

推导的一般步骤:

  • 用常数1取代运算中的所有加法常数
  • 在修改后的运行次数中,只保留最高项
  • 如果最高项阶存在且不为1,则去除与这个项相乘的参数

接下来举几个栗子:

#include <stdio.h>

int main()
{
    printf("Hello, World! \n");
    printf("Hello, World! \n");
    printf("Hello, World! \n");
    printf("Hello, World! \n");
    printf("Hello, World! \n");
    printf("Hello, World! \n");
    
    return 0;
}

在上面的main中,printf一共打印为6次,这里绝不要理解为算法时间复杂度就是O(6),根据推导大O的阶的推导步骤,可以得出算法的时间复杂度为O(1)。

    int n=100,sum=0;          //1
    for(int i=0;i<n;i++){     //n
        sum+=(i+1);
    }
    printf("%d",sum);         //1

这个算法求得1到100的和,总的执行次数为n+2(注意:这里只是大致分析,该代码转化为汇编语言的命令行数绝不止这几行),根据推导规则就是O(n)。

接下来介绍一下高斯算法:

    int n=100;
    int sum=0;
    sum=(1+n)*n/2;
    printf("%d",sum);

可以看出,高斯算法的效率非常高,无论求的数之和有多大,算法的时间复杂度都为O(1)。

接来是一个对数阶的栗子:

    int i=1,n=100;          //1
    while(i<n){             //x
        i=i*2;
    }
    printf("%d",i);         //1

从上面这行代码中,不能直观的观察出while的循环次数,可以假设循环x次,每一次i都乘于2,所以满足这个条件2^x=n;就可以让程序退出循环。推导可以推出x=logn,所以大O阶为:O(logn)。

 3.最优、平均、最差时间复杂度

时间复杂度就是循环次数,那么最优时间复杂度就是考虑循环次数最少的复杂度,最差时间复杂度就是循环次数最多的复杂度,平均时间复杂度就是取中间值。最差时间复杂度是讨论一个算法必需要衡量的一个复杂度。通常情况下,出现最优、平均、最差时间复杂度是因为排序的次数和需要排序的元素大小有关。上面的几个栗子中,就只有一个算法复杂度。比如插入排序,快排等算法的循环次数就和元素的大小、排列顺序有关,他们就具有最优、平均、最差时间复杂度。

 

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!