前言

本笔记主要记录如何分析、统计算法的执行效率和资源消耗

必须学会分析复杂度分析。

李柱明博客:https://www.cnblogs.com/lizhuming/p/15487271.html

复杂度

复杂度分为:

  1. 时间复杂度。关联到执行效率

    • 时间复杂度的全称是 渐进时间复杂度表示算法的执行时间与数据规模之间的增长关系
  2. 空间复杂度。关联到资源消耗

    • 空间复杂度全称就是渐进空间复杂度表示算法的存储空间与数据规模之间的增长关系

分析方法

大 O 复杂度表示法

先说结论:

  • 大 O 复杂度表示方法只是表示一种变化趋势。
  • 忽略掉公式中的常量、低阶、系数,只需要记录一个最大阶的量级就可以了
  • 多、加法和乘法规则

例子-评估累加和的各种算法执行效率

算法 1(for 循环):
  1. int cal(int n)
  2. {
  3. int sum = 0;
  4. int i = 1;
  5. for (; i <= n; ++i)
  6. {
  7. sum = sum + i;
  8. }
  9. return sum;
  10. }
  • 从 CPU 角度看:

    • 重复类似的操作:读数据-运算-写数据。
    • 假设每行代码执行事件都为 unit_time。(粗略估计)
    • 代码中执行的时间为:T(n) = (2+3n)*unit_time
  • 结论:所有代码的执行时间 T(n) 与每行代码的执行次数成正比。

算法 2(嵌套 for 循环):
  1. int cal(int n)
  2. {
  3. int sum = 0;
  4. int i = 1;
  5. int j = 1;
  6. for (; i <= n; ++i)
  7. {
  8. j = 1;
  9. for (; j <= n; ++j)
  10. {
  11. sum = sum + i * j;
  12. }
  13. }
  14. }
  • 代码中执行时间为:T(n) = (3+3n+3n²)*unit_time=3(n²+n+1)*unit_time
  • 所有代码的执行时间 T(n) 与每行代码执行的次数成正比。

大 O 表示

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

  • 上面算法 1 中的大 O 表示法为:T(n) = O(2+3n)

  • 上面算法 2 中的大 O 表示法为:T(n) = O(3(n²+n+1))

  • 大 O 表示法不是表示代码真正的执行时间,而是表示代码执行时间随数据规模增长的变化趋势

    • 即是时间复杂度

当 n 很大时,公式中的低阶常量系数三部分并不左右增长趋势,所以都可以忽略。

只需要记录一个最大量级就可以了,如果用大 O 表示法表示刚讲的那两段代码的时间复杂度,可记为:

  • T(n) = O(n)
  • T(n) = O(n²)

时间复杂度分析

当了解了大 O 表示法后,就可以用来分析时间复杂度了。

三个实用的方法:

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

关注执行最多的一段代码

以上面算法 1 为例:

  • 前面两行代码为常量级别,忽略。

  • 3n 中的系数也可忽略。

  • 结论:时间复杂度为 O(n)

算法 2 的时间复杂度就是 O(n²)

加法规则

加法法则:总复杂度等于量级最大的那段代码的复杂度

  • 公式:T(n)=T1(n)+T2(n)=max(O(f(n)), O(g(n))) =O(max(f(n), g(n)))

若上面算法 1 和算法 2 出现在同一个代码段中是,其时间复杂度之和为 O(n)+O(n²)

总的时间复杂度就是取最大量级: O(n²)

乘法规则

乘法法则:嵌套代码的复杂度等于嵌套内外代码复杂度的乘积

  • 公式:T1(n)=O(f(n))T2(n)=O(g(n));那么 T(n)=T1(n)T2(n)=O(f(n))O(g(n))=O(f(n)*g(n))

例子:

  • 时间复杂度:T(n) = T1(n) * T2(n) = O(n*n) = O(n²)
  1. int func(int n)
  2. {
  3. int sum = 0;
  4. int i = 1;
  5. for (; i < n; ++i)
  6. {
  7. sum = sum + i;
  8. }
  9. return sum;
  10. }
  11. int cal(int n)
  12. {
  13. int ret = 0;
  14. int i = 1;
  15. for (; i < n; ++i)
  16. {
  17. ret = ret + func(i);
  18. }
  19. }

常见时间复杂度

常见时间复杂度量级如图:

这些复杂度量级可分为:

  • 多项式量级:

    • 常量阶:O(1)
    • 对数阶:O(logn)
    • 线性阶:O(n)
    • 线性对数阶:O(nlogn)
    • k 次方阶:O(nk)注意:这里的 k 为 k 次方)
  • 非多项式量级

    • O(2n);(注意:这里的 n 为 n 次方)
    • O(n!)
    • 说明:当数据规模 n 越来越大时,非多项式量级算法的执行时间会急剧增加,求解问题的执行时间会无限增长。所以,非多项式时间复杂度的算法其实是非常低效的算法

常量阶 O(1)

O(1) 只是常量级时间复杂度的一种表示方法,并不是指只执行了一行代码。

大牛总结:(常量级记作 O(1)

  • 只要代码的执行时间不随 n 的增大而增长,这样代码的时间复杂度我们都记作 O(1)
  • 或者说, 一般情况下,只要算法中不存在循环语句、递归语句,即使有成千上万行的代码,其时间复杂度也是 Ο(1)

对数阶 O(logn)、O(nlogn)

  1. i=1;
  2. while (i <= n)
  3. {
  4. i = i * 2;
  5. }

时间复杂度分析过程:

  • 多:第 4 行代码执行次数最多。那就算出第四行执行的次数。

  • 得 x = log2n 即时间复杂度为 O(log2n)。也就是 O(logn)

  • 不管底数为何值,都把这类对数阶的时间复杂度记为 O(logn)。理由:

    • log3n = log32 * log2n。对应时间复杂度为:O(log3n) = O(C * log2n)。
    • 按前面学的系数可忽略:O(log3n) = O(log2n)。
    • 既然不同底数都可以转化,那就直接使用 O(logn) 来标记对数阶。

而对于 O(nlogn) 就是一段时间复杂度为 O(logn) 的代码段被执行了 n 次。

多参数阶 O(m+n)、O(m*n)

分析代码的时间复杂度由两个以上数据的规模来决定。

以下以两个数据规模决定为基础。

  1. int cal(int m, int n)
  2. {
  3. int sum_1 = 0;
  4. int i = 1;
  5. for (; i < m; ++i)
  6. {
  7. sum_1 = sum_1 + i;
  8. }
  9. int sum_2 = 0;
  10. int j = 1;
  11. for (; j < n; ++j)
  12. {
  13. sum_2 = sum_2 + j;
  14. }
  15. return sum_1 + sum_2;
  16. }
  • 其时间复杂度为:O(m+n)
  • 对于加法规则(变了):T1(m) + T2(n) = O(f(m) + g(n))。
  • 对于乘法规则(不变):T1(m)*T2(n) = O(f(m) * f(n))。

空间复杂度分析

空间复杂度。关联到资源消耗

  • 空间复杂度全称就是渐进空间复杂度表示算法的存储空间与数据规模之间的增长关系

使用大 O 表示法,和时间复杂度一样,只是分析的数据规模 n 由时间度量改为空间度量。

小结

复杂度也叫渐进复杂度,包括时间复杂度和空间复杂度,用来分析算法执行效率与数据规模之间的增长关系。

通常越高阶复杂度的算法,执行效率越低。

常见的复杂度并不多,从低阶到高阶有:O(1)、O(logn)、O(n)、O(nlogn)、O(n2 )。

【数据结构&算法】02-复杂度分析之执行效率和资源消耗的更多相关文章

  1. 《数据结构与算法之美》 <01>复杂度分析(上):如何分析、统计算法的执行效率和资源消耗?

    我们都知道,数据结构和算法本身解决的是“快”和“省”的问题,即如何让代码运行得更快,如何让代码更省存储空间.所以,执行效率是算法一个非常重要的考量指标. 那如何来衡量你编写的算法代码的执行效率呢?这里 ...

  2. Chapter3 复杂度分析(上):如何分析,统计算法的执行效率和资源消耗

    数据结构解决的问题:“快” + “省”,即为时间,空间复杂度分析 1:为什么需要复杂度分析? 因为通过统计手段分析的结果受到两个因素的影响,一:测试结果非常依赖测试环境,二:测试结果受数据规模的影响很 ...

  3. 重拾算法之复杂度分析(大O表示法)

    .katex { display: block; text-align: center; white-space: nowrap; } .katex-display > .katex > ...

  4. 三行代码实现.NET MVC统计显示页面的执行时间 超简单的实现方法 分析页面执行效率

    三行代码实现.NET MVC统计显示页面的执行时间 超简单的实现方法 分析页面执行效率    博客页脚处添加了页面执行时间统计显示,如下图所示,也可以直接查看网页页脚处. 实现方法非常简单,只需三行代 ...

  5. 《数据结构与算法之美》 <02>复杂度分析(下):浅析最好、最坏、平均、均摊时间复杂度?

    上一节,我们讲了复杂度的大 O 表示法和几个分析技巧,还举了一些常见复杂度分析的例子,比如 O(1).O(logn).O(n).O(nlogn) 复杂度分析.掌握了这些内容,对于复杂度分析这个知识点, ...

  6. 数据结构与算法 java描述 第一章 算法及其复杂度

    目录 数据结构与算法 java描述 笔记 第一章 算法及其复杂度 算法的定义 算法性能的分析与评价 问题规模.运行时间及时间复杂度 渐进复杂度 大 O 记号 大Ω记号 Θ记号 空间复杂度 算法复杂度及 ...

  7. 八大排序算法详解(动图演示 思路分析 实例代码java 复杂度分析 适用场景)

    一.分类 1.内部排序和外部排序 内部排序:待排序记录存放在计算机随机存储器中(说简单点,就是内存)进行的排序过程. 外部排序:待排序记录的数量很大,以致于内存不能一次容纳全部记录,所以在排序过程中需 ...

  8. 八大排序算法——希尔(shell)排序(动图演示 思路分析 实例代码java 复杂度分析)

    一.动图演示 二.思路分析 希尔排序是把记录按下标的一定增量分组,对每组使用直接插入排序算法排序:随着增量逐渐减少,每组包含的关键词越来越多,当增量减至1时,整个文件恰被分成一组,算法便终止. 简单插 ...

  9. 八大排序算法——插入排序(动图演示 思路分析 实例代码java 复杂度分析)

    一.动图演示 二.思路分析 例如从小到大排序: 1.  从第二位开始遍历, 2.  当前数(第一趟是第二位数)与前面的数依次比较,如果前面的数大于当前数,则将这个数放在当前数的位置上,当前数的下标-1 ...

随机推荐

  1. jmeter长时间压测

    如何进行24h小时的压测? 长时间压测注意事项 生成报告文件过大 https://www.cnblogs.com/SunshineKimi/p/12298668.html

  2. Navicat连接数据库成功,新建查询时提示错误“Cannot create file ……”

    Navicat连接数据库成功,新建查询时提示错误"Cannot create file --" 原因:编辑连接{高级}<设置位置>被修改,该oci.dll不正确 解决方 ...

  3. 鸿蒙内核源码分析(异常接管篇) | 社会很单纯 , 复杂的是人 | 百篇博客分析OpenHarmony源码 | v39.03

    百篇博客系列篇.本篇为: v39.xx 鸿蒙内核源码分析(异常接管篇) | 社会很单纯,复杂的是人 | 51.c.h .o 硬件架构相关篇为: v22.xx 鸿蒙内核源码分析(汇编基础篇) | CPU ...

  4. SpringSecurity系列学习(一):初识SpringSecurity

    SpringSecurity Spring Security是spring采用AOP思想,基于servlet过滤器实现的安全框架.它提供了完善的认证机制和方法级的 授权功能.是一款非常优秀的权限管理框 ...

  5. 数据库的规范和SQL优化技巧总结

    现总结工作与学习中关于数据库的规范设计与优化技巧 1.规范背景与目的 MySQL数据库与 Oracle. SQL Server 等数据库相比,有其内核上的优势与劣势.我们在使用MySQL数据库的时候需 ...

  6. ❤️❤️新生代农民工爆肝8万字,整理Python编程从入门到实践(建议收藏)已码:8万字❤️❤️

    @ 目录 开发环境搭建 安装 Python 验证是否安装成功 安装Pycharm 配置pycharm 编码规范 基本语法规则 保留字 单行注释 多行注释 行与缩进 多行语句 数据类型 空行 等待用户输 ...

  7. WebMagic 爬虫技术

    WebMagic WebMagic 介绍 WebMagic基础架构 Webmagic 的结构分为 Downloader.PageProcessor.Scheduler.Pipeline四大组件,并由 ...

  8. 数字图像处理(一)之灰度转换和卷积python实现

    使用Python实现数字图像处理中如下功能: 彩色图像转成灰度图像 实现图像的相关&卷积操作 实现图像的高斯核卷积 使用的库和python版本如下: imageio:2.9.0 用于读取磁盘中 ...

  9. oracle查看和修改session和最大连接数

    第一步,在cmd命令行,输入sqlplus 第二步,根据提示输入用户名与密码 1. 查看processes和sessions参数 SQL> show parameter processes NA ...

  10. Spring配置文件结构对于生成Bean的影响

    Spring配置文件结构对于生成Bean的影响 有段时间忙于毕设,导致Spring学习的东西忘了很多,所以最近又开始从头看Spring的基础.基础的Bean的装配不再多说了.这一次,主要是深入一点了解 ...