第1讲 | 数据结构与算法 | 【复杂度分析】

本文介绍了复杂度分析在优化代码效率中的重要性,详细讲解了大O复杂度表示法,强调了时间复杂度和空间复杂度分析,并提到了最好、最坏、平均和均摊时间复杂度的概念。通过实例解析了如何计算和理解不同复杂度量级,如O(1), O(logn), O(n), O(nlogn), O(n2)等。" 122467337,8760888,GEE数据导出至共享盘策略,"['google earth', 'python', '数据导出', '云存储']

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

- 《数据结构与算法》专栏完整版在公众号【书伟认视界】中查看,转载需联系微信【econe0219


复杂度分析

数据结构与算法本身解决的问题就是,如果让代码运行更快,更省存储空间。时间、空间的复杂度分析就是来解决算法的执行效率的问题。

所谓的时间、空间复杂度分析,就是在不用具体的数据来测试的情况下,就可以粗略估计算法的执行效率。

大O复杂度表示法

公式: T ( n ) = O ( f ( n ) ) T(n) = O(f(n)) T(n)=O(f(n))

其中, T ( n ) T(n) T(n): 代码执行的时间; n n n: 数据规模的大小; f ( n ) f(n) f(n): 每行代码执行的次数总和; O O O: 表示代码的执行时间 T ( n ) T(n) T(n) f ( n ) f(n) f(n)表达式成正比。

eg.

// 求前n项和
int cal(int n)  {
    int sum = 0;
    int i = 1;
    for (; i<=n; ++i)  {
        sum = sum + i;
    }
    return sum;
}

假设每行代码执行时间都一样(粗略估计),设为 unit_time。那么,(不算注释行)第2、3行代码分别需要1个unit_time的执行时间,第4、5行代码都运行了n遍,需要2n*unit_time的执行时间。所以这段代码总的执行时间就是(2n+2)*unit_time( f ( n ) = 2 n + 2 f(n)=2n+2 f(n)=2n+2)。可以知道,所有代码的执行时间 T ( n ) T(n) T(n)与每行代码的执行次数成正比。

注意:O时间复杂度实际上并不具体表示代码真正的执行时间,而是表示代码执行时间随数据规模增长的变化趋势。公式中的低阶、常量、系数三部分并不左右增长趋势,可以忽略。以上例子用大O表示法表示的代码时间复杂度就是 T ( n ) = O ( n ) T(n)=O(n) T(n)=O(n)

时间复杂度分析

分析时间复杂度的技巧方法:

  1. 只需要关注循环执行次数最多的一段代码;
  2. 代码总复杂度等于量级最大的那段代码的复杂度;
  3. 嵌套代码的复杂度等于嵌套内外代码复杂度的乘积。

复杂度量级(按数量级递增)

多项式量级非多项式量级
常量阶: O ( 1 ) O(1) O(1)指数阶: O ( 2 n ) O(2^n) O(2n)
对数阶: O ( l o g n ) O(log n) O(logn)阶乘阶: O ( n ! ) O(n!) O(n!)
线性阶: O ( n ) O(n) O(n)
线性对数阶: O ( n l o g n ) O(nlogn) O(nlogn)
平方阶: O ( n 2 ) O(n^2) O(n2)、立方阶:O(n^3)···k次方阶: O ( n k ) O(n^k) O(nk)

非多项式量级(NP问题)在数据量越来越大时,算法的执行时间会急剧增加。

一般来讲(不讨论数据规模问题),越高阶复杂度的算法,执行效率越低。最常见的从低阶到高阶有: O ( 1 ) 、 O ( l o g n ) 、 O ( n ) 、 O ( n l o g n ) 、 O ( n 2 ) O(1)、O(logn)、O(n)、O(nlogn)、O(n^2) O(1)O(logn)O(n)O(nlogn)O(n2)

  1. O(1)

只要代码执行时间不随着n的增大而增大,这样代码的时间复杂度记作 O ( 1 ) O(1) O(1)

  1. O(logn)、O(nlogn)
i = 1;
while (i <= n)  {
    i = i*2;
}

如上这段代码的执行次数 x = l o g 2 n x=log_{2}n x=log2n ( 2 x = n ) (2^x=n) (2x=n),所以时间复杂度就是 O ( l o g 2 n ) O(log_{2}n) O(log2n)。对数是可以转化的,比如 l o g 3 n = l o g 3 2 ∗ l o g 2 n log_{3}n=log_{3}2*log_{2}n log3n=log32log2n,所以不管底数是几,都可以把对数阶的时间复杂度记为 O ( l o g n ) O(logn) O(logn)。如果一点代码的时间复杂度是 O ( l o g n ) O(logn) O(logn),循环执行n次,时间复杂度就是 O ( n l o g n ) O(nlogn) O(nlogn)。归并、快速排序的时间复杂度就是 O ( n l o g n ) O(nlogn) O(nlogn)

  1. O(m+n)、O(m*n)

如果一个程序快中包含执行次数分别为m和n的两段代码,无法评估m和n的大小,那么就用 O ( m + n ) O(m+n) O(m+n)来表示时间复杂度。两段嵌套的线性阶执行次数的程序段的时间复杂度用 O ( m ∗ n ) O(m*n) O(mn)表示。

空间复杂度分析

空间复杂度,表示算法算法的存储空间与数据规模之间的增长关系。

空间复杂度相对简单很多,常用的就是 O ( 1 ) 、 O ( n ) 、 O ( n 2 ) O(1)、O(n)、O(n^2) O(1)O(n)O(n2)

最好、最坏、平均、均摊时间复杂度

最好情况时间复杂度是指,在最理想的情况下,执行某段代码的时间复杂度;同理,最坏情况时间复杂度就是,在最糟糕情况下,执行某段代码的时间复杂度;平均时间复杂度需要考虑每种情况出现的概率,加权之后得到。通常来讲,由于低阶、常量和系数不影响变化趋势,平均时间复杂度和最坏/最好时间复杂度一致。大多数情况下,也不需要区分这三种时间复杂度,取其一即可。

均摊时间复杂度,属于更特殊的一种平均时间复杂度,使用均摊分析法来分析,所谓均摊分析法就是把耗时多的那次操作均摊到耗时少的一系列操作上。其应用场景是,大部分情况下时间复杂度都很低,只有个别情况下时间复杂度比较高,而且这些操作之间存在连贯的时序关系,这个时候 ,我们就可以将这一组操作放在一块儿分析,看是否能将较高时间复杂度那次操作的耗时,平摊到其他那些时间复杂度比较低的操作上。

这个不理解也没有关系,有个概念就好了,遇到实际问题再上网查。




《数据结构与算法》专栏完整版在公众号【书伟认视界】中查看,转载需联系微信【econe0219

.

在这里插入图片描述

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值