算法及时间、空间复杂度

算法必须具备有穷性、确定性、可行性、输入和输出等特性。时间复杂度关注算法执行时间随问题规模增长的趋势,常用大O符号表示,如O(n),O(n^2)等。空间复杂度衡量算法执行过程中所需的最大存储空间。常见的空间复杂度包括O(1),O(n)等。复杂度分析涉及最坏、最好、平均和均摊时间复杂度。
摘要由CSDN通过智能技术生成

算法

算法是对问题求解过程的一种描述,是为解决一个或一类问题给出的一个确定的、有限长的操作序列。严格说来,一个算法必须满足以下5个重要特性:
(1)有穷性:对于任意一组合法的输入值,在执行有穷步骤之后一定能结束,即算法中的操作步骤为有限个,且每个步骤都能在有限时间内完成。
(2)确定性:对于每种情况下所应执行的操作,在算法中都有确切的规定,使算法的执行者和阅读者都能明确其含义及如何执行。并且在任何条件下,算法都只有一条执行路径
(3)可行性:算法中的所有操作都必须足够基本,都可以通过已经实现的基本操作运算有限次实现。
(4)有输入:作为算法加工对象的量值,通常体现为算法中的一组变量。有些输入量需要在算法执行过程中输入,而有的算法表面上可以没有输入,实际上输入已被嵌入算法之中。
(5)有输出:它是一组与“输入”有确定关系的量值,是算法进行信息加工后得到的结果,这种确定关系即为算法的功能。

时间复杂度

算法的效率指的是算法的执行时间随问题规模的增长而增长的趋势。假如随着问题规模n的增长,算法执行时间的增长率和f(n)的增长率相同,则可记作:

T(n)=O(f(n))

称T(n)为算法的(渐近)时间复杂度。
T(n)表示代码执行的时间; n表示数据规模的大小; f(n) 表示每行代码执行的次数总和。因为这是一个公式,所以可以用f(n)来表示。公式中的O,表示的是代码的执行时间T(n)与f(n)表达式成正比。

当n很大时,你可以把它想象成999999、9999999999。 而公式中的低阶、常量、系数三部分并不左右增长趋势,所以都可以忽略。我们只需要记录一个最大量级就可以了。

比如:
T(n)=O(5n+5),将它的系数和常量忽略,就可以看成是T(n)=O(n);
T(n)=O(5n2+5n+5),将它的低阶、常量、系数三部分忽略后,就可以看成是T(n)=O(n2)。

复杂度分析法则:
(1)单段代码看高频:比如循环。
(2)多段代码取最大:比如一段代码中有单循环和多重循环,那么取多重循环的复杂度。
(3)嵌套代码求乘积:比如递归、多重循环等
(4)多个规模求加法:比如方法有两个参数控制两个循环的次数,那么这时就取二者复杂度相加。

时间复杂度分析:
只关注循环执行次数最多的一段代码
加法法则:总复杂度等于量级最大的那段代码的复杂度
乘法法则:嵌套代码的复杂度等于嵌套内外代码复杂度的乘积

几种常见的时间复杂度:

在这里插入图片描述

如果一段代码的时间复杂度是O(logn) ,我们循环执行 n 遍,时间复杂度就是 O(nlogn) 。
多项式阶:随着数据规模的增长,算法的执行时间和空间占用,按照多项式的比例增长。包括,O(1)(常数阶)、O(logn)(对数阶)、O(n)(线性阶)、O(nlogn)(线性对数阶)、O(n2)(平方阶)、O(n3)(立方阶)
非多项式阶:随着数据规模的增长,算法的执行时间和空间占用暴增,这类算法性能极差。包括,O(2n)(指数阶)、O(n!)(阶乘阶)

求下列程序段的时间复杂度:

i=1;
while(i<=n) 
{
   i = i*3;
}

假设循环执行次数是k,则i=3k-1。转化一下,有3k-1<=n,解之得到在这里插入图片描述
所以时间复杂度是O(logn)。

空间复杂度

算法的存储量指的是算法执行过程中所需的最大存储空间。算法执行期间所需要的存储量应该包括以下三部分:
(1)输入数据所占空间
(2)程序本身所占空间
(3)辅助变量所占空间

类似于算法的时间复杂度,通常以算法的空间复杂度作为算法所需存储空间的量度。定义算法空间复杂度为

S(n)=O(g(n))

表示随着问题规模n的增大,算法运行所需存储量的增长率与g(n)的增长率相同。

空间复杂度也是一个数学函数表达式,是对一个算法在运行过程中临时占用存储空间大小的量度。空间复杂度不是程序占用了多少bytes的空间,因为这个也没太大意义,所以空间复杂度算的是变量的个数。
注意:函数运行时所需要的栈空间(存储参数、局部变量、一些寄存器信息等)在编译期间已经确定好了,因此空间复杂度主要通过函数在运行时候显式申请的额外空间来确定

常见的空间复杂度就是O(1)、O(n)、O(n2),像O(logn)、O(nlogn)这样的对数阶复杂度平时都用不到。

在这里插入图片描述

举例:

void print(int n) 
{
    int i=0;
    int[]a=new int[n];
    for (i;i<n;++i) 
    {
        a[i]=i*i;
    }
    for(i=n-1;i>=0;--i)
    {
        print out a[i]
    }
}

我们可以看到,第三行代码中,我们申请了一个空间存储变量i,但是它是常数阶的,跟数据规模n没有关系,所以我们可以忽略。第四行申请了一个大小为n的int类型数组,除此之外,剩下的代码都没有占用更多的空间,所以整段代码的空间复杂度就是O(n)。

复杂度分析的4个概念:
1.最坏情况时间复杂度:代码在最坏情况下执行的时间复杂度。
2.最好情况时间复杂度:代码在最理想情况下执行的时间复杂度。
3.平均时间复杂度:代码在所有情况下执行的次数的加权平均值。
4.均摊时间复杂度:在代码执行的所有复杂度情况中绝大部分是低级别的复杂度,个别情况是高级别复杂度且发生具有时序关系时,可以将个别高级别复杂度均摊到低级别复杂度上。基本上均摊结果就等于低级别复杂度。

三、如何分析平均、均摊时间复杂度?
1.平均时间复杂度
代码在不同情况下复杂度出现量级差别,则用代码所有可能情况下执行次数的加权平均值表示。
2.均摊时间复杂度
两个条件满足时使用:(1)代码在绝大多数情况下是低级别复杂度,只有极少数情况是高级别复杂度;(2)低级别和高级别复杂度出现具有时序规律。均摊结果一般都等于低级别复杂度。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

tyro达令

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

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

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

打赏作者

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

抵扣说明:

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

余额充值