最近练习算法题,又看了极客时间中的《数据结构与算法之美》写的真不错,于是总结一下关于复杂度的知识,代码和图片都是课程里面的。虽然是按课程写的,但是自己写一遍最好,否则看过就忘了。

数据结构与算法本身解决的是的问题。如何让代码运行的更快,如何更省空间有个重要的标准:复杂度分析

一、大 O 复杂度表示法

算法的执行效率,粗略的讲就是算法代码执行的时间,在我们不做精确监控统计,靠观察怎么分析代码执行的时间呢?

int cal(int n) {int sum = 0;--------2int i = 1;--------3for (; i <= n; ++i) {--------4sum = sum + i;--------5}return sum;}

上面这段代码是计算1到n的累加和,从CPU的角度来看每一行的执行都是:读数据-计算-写数据。尽管每行代码对应的CPU执行时间都不一样,做粗略计算的时候只需要估算,把这个时间看成相同的一个时间:unit_time。

2,3行代码分别需要1*unit_time,for循环里面的第4,5行需要n*unit_time,得到的结果是2*unit_time+2n*unit_time = (2n+2)*unit_time。得出一个结论:所有代码执行的时间T(n)与每行代码执行的时间unit_time成正比

按照这个方法看下面一段代码:

int cal(int n) {int sum = 0;--------2int i = 1;--------3int j = 1;--------4for (; i <= n; ++i) {--------5j = 1;--------6for (; j <= n; ++j) {--------7sum = sum +  i * j;--------8}}}

2,3,4分别行执行了1次总共3*unit_time,5,6行分别执行了n*unit_time,7,8行分别执行了n^2*unit_time,总共是(2n^2+2n+3)*unit_time.尽管不知道*unit_time的具体值,但还是得到那个规律:代码执行的时间T(n)与每行代码执行的次数f(n)成正比

总结一个公式就是:

  1. T(n)表示代码执行时间
  2. n是数据规模
  3. f(n)是每行代码执行次数总和
  4. O表示代码执行时间和代码执行总次数成正比

所以第一段代码的T(n) = O(2n+2),第二段代码的T(n) = O(2n^2+2n+3)这就是时间复杂度(asymptotic time complexity)的表示方法

而代码规模n很大时就可以忽略掉低阶,常量和系数,最终得到,第一段代码的T(n) = O(n),第二段T(n) = O(n^2)

二、时间复杂度分析

1.只关注循环执行次数最对的代码

就像上面第一段代码,我们只关注for循环的运行次数就可以得出这段代码的时间复杂度是T(n) = O(n)

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

这里有段代码,我们分析一下


int cal(int n) {int sum_1 = 0;int p = 1;for (; p < 100; ++p) {sum_1 = sum_1 + p;}int sum_2 = 0;int q = 1;for (; q < n; ++q) {sum_2 = sum_2 + q;}int sum_3 = 0;int i = 1;int j = 1;for (; i <= n; ++i) {j = 1; for (; j <= n; ++j) {sum_3 = sum_3 +  i * j;}}return sum_1 + sum_2 + sum_3;}

这段代码可以分为三部分sum_1、sum_2、sum_3

  1. 第一部分for'循环了100次,时间复杂度是O(1),常数级别的如果有更高阶可以忽略掉,为什么是O(1)下面解释
  2. 第二部分的时间复杂度分别是O(n)
  3. 第三部分的时间复杂度分别是O(n^2)

很显然最高阶是第三部分,所以这段代码的时间复杂度是O(n^2)

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

看一段代码


int cal(int n) {int ret = 0; int i = 1;for (; i < n; ++i) {ret = ret + f(i);} } int f(int n) {int sum = 0;int i = 1;for (; i < n; ++i) {sum = sum + i;} return sum;}

for循环里面嵌入的方法f(x)的时间复杂度为O(n)外部for循环的复杂度是O(n)那么这段代码的时间复杂度就是O(n*n)=O(n^2)。其实还是跟上面分析的一样是两个否循环的嵌套跟2中那个最高阶的一样。

三、常见的时间复杂度实例

上面这些可以分两类,多项式量级非多项式量级,其中费多项式量级只有划黄色下划线那两个。非多项式量级的算法问题叫作 NP(Non-Deterministic Polynomial,非确定多项式)问题。

按我们的数学知识,非多项式量级的时间复杂度会随数据规模n的增大而急剧增大,求解问题的执行时间会无线增长,所以非多项式量级的算法其实效率非常低。所以不多去分析了,只分析多项式量级算法。

1.O(1)

看段代码

 int i = 8;int j = 6;int sum = i + j;

这段代码的时间复杂度并不是O(3)而是O(1),只要代码的运行时间不随n的增大而增长我们都记作O(1),只要不存在递归和循环,再多行代码的时间复杂度都是O(1)

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

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

不难看出这段代码的第三行的阶数最高,i的取值是个等比数列

x=如果把2换成3就有其实不管底是2,3还是10时间复杂度都可以记为O(logn)因为=(C * 其中C = 是个常数可以忽略,对数阶时间复杂度表示的时候可以省略调对数的底,统一写成O(logn)。理解了这个O(nlogn)其实就不难理解了,就是一个嵌套的乘法法则,一个循环嵌套一个时间复杂度为O(logn)的代码。比如归并排序和快速排序的时间复杂度都是O(nlogn)

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

代码的时间复杂度由两种数据的规模来决定


int cal(int m, int n) {int sum_1 = 0;int i = 1;for (; i < m; ++i) {sum_1 = sum_1 + i;}int sum_2 = 0;int j = 1;for (; j < n; ++j) {sum_2 = sum_2 + j;}return sum_1 + sum_2;
}

像这种我们无法预估m和n的量级谁的比较大,所以无法用加法法则忽略掉一个,所以表示为O(m+n),但乘法法则依然有效所以可以有O(m * n)

四、空间复杂度

空间复杂度的全称是渐进空间复杂度(asymptotic space complexity),表示的是算法的存储空间跟数据规模的增长关系。看代码:

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]}
}

代码中申请了一个长度为n的数组,其他地方没有占用到更多空间,所以空间复杂度就是O(n),常见的空间复杂度就是 O(1)、O(n)、O(n2 ),像 O(logn)、O(nlogn) 这样的对数阶复杂度平时都用不到。而且,空间复杂度分析比时间复杂度分析要简单很多。

代码复杂度分析——时间、空间复杂度相关推荐

  1. 数据结构与算法分析c++第四版_数据结构与算法 - 时空复杂度分析

    这周主要总结了时间复杂度的学习,跟小伙伴们分享下,欢迎指正. 一.为何需要分析算法复杂度 挺多同学本科都学习过数据结构和算法这门课,但是有没有想过这门课到底是解决什么问题?科学家设计这些数据结构和算法 ...

  2. matlab 趋势分析,科学网—SEN趋势度分析及其MATLAB实现 - 杨建华的博文

    SEN趋势度分析及其MATLAB实现 一.博文概述 1.目的 学习理解SEN趋势度分析方法及其应用,并编写简易的SEN趋势度分析函数 2.时间 2016年12月24日 3.关键词 SEN趋势度分析   ...

  3. 算法及时间/空间复杂度的分析

    算法(Algorithm) 对特定问题求解步骤的一种描述,是为解决一个或一类问题给出的一个确定的.有限长的操作序列 算法的基本特征 ①输入:有零个或多个输入 ②输出:有一个或多个输出 ③有穷性:在执行 ...

  4. BFS、DFS复杂度分析(时间、空间)

    一.BFS的复杂度分析 BFS是一种借用队列来存储的过程,分层查找,优先考虑距离出发点近的点.无论是在邻接表还是邻接矩阵中存储,都需要借助一个辅助队列,v个顶点均需入队,最坏的情况下,空间复杂度为O( ...

  5. 简单排序算法时间空间复杂度分析及应用(4)-二分插入排序

    简单排序算法时间空间复杂度分析及应用(4)-二分插入排序 背景: 顾名思义,这个二分插入排序是直接插入排序的进化版,主要变化的地方就是在内循环部分,即外循环的循环节点在确定区域的位置查询方式由原来的直 ...

  6. 素数判断的几种方法代码实现及其复杂度分析

     素数判断的几种方法代码实现及其复杂度分析  原文链接:http://blog.csdn.net/infinitezhen/article/details/8961964 一. 朴素判断素数 根据素数 ...

  7. 算法设计与分析课程的时间空间复杂度

    算法设计与分析课程的时间空间复杂度: 总结 算法 时间复杂度 空间复杂度 说明 Hanoi $ O(2^n) $ $ O(n) $ 递归使用 会场安排问题 \(O(nlogn)\) \(O(n)\) ...

  8. 动态分区分配算法代码_【代码】巩敦卫等TEVC论文:基于区间相似度分析的协同动态区间多目标进化优化算法...

    分享代码:巩敦卫等TEVC论文:基于区间相似度分析的协同动态区间多目标进化优化算法. 说明:该代码基于Matlab2012a及Intlab5.5编写,对应文献:"Dunwei Gong, B ...

  9. 简单排序算法时间空间复杂度分析及应用(7)-希尔排序

    希尔排序,属于插入排序的一种,是直接插入排序的加强版.在希尔排序中引入了步长(gap)的概念,然而在插入排序中,步长默认为1.正如我们直接堆插入排序的分析,数据集合的排列顺序对插入排序的效率会由很大的 ...

最新文章

  1. [na]tcpdump非常实用的抓包实例
  2. verilog实例_Verilog设计与逻辑综合实例解析(含代码)(Tasks amp;Functions)
  3. ITK:基于零交叉的边缘检测器
  4. tomcat闪退没有报错_Appium在Android平台几种常见报错的解决方案
  5. PHP常用字符串函数小结
  6. 国产自主可控的代码自动生成工具SkyEye
  7. js一次获取整个表单的数据
  8. erlang有前途吗_带有示例的Erlang概述
  9. Android画布和图形绘制---Canvas and Drawables(一)
  10. java qrious 二维码中文无反应_来了来了,今天的苹果限免应用刚刚出炉,8款APP在App Store限时免费啦!手慢无~...
  11. 景驰无人车披露最新技术进展,2年后开启国内规模化运营 | 视频
  12. 数字电路逻辑设计_第三版_微课版_第三章思考题与练习题(附答案)
  13. c语言一些简单的程序
  14. html模板查询,前台模板查找
  15. ios描述文件安装的问题
  16. 你应该知道的三相电机知识
  17. C#窗体加标尺的两种方式及显现效果
  18. 安卓framework层开发!给后辈的一点建议,持续更新中
  19. 微服务架构中职能团队的划分
  20. 利用计算机设计轴对称图案,“轴对称图形”信息技术应用设计与分析|轴对称图形有哪些图片...

热门文章

  1. pandas读取行列数据-详细介绍(连续不连续)
  2. 【LaTeX】表格调整行高、列宽、合并显示等操作
  3. 达梦数据库安装(Linux下的命令行方式)_yxy
  4. 高通ims架构android,深度揭密高通4/5G移动基带消息系统和状态机
  5. 乐乐音乐4.0简洁版
  6. PS中的颜色模式,8位、16位、32位区别、以及背景内容的区别
  7. Web3的先锋兵:虚拟人
  8. (附源码)springboot社区养老医疗服务平台 毕业设计 041148
  9. android#boardcast#发送自定义广播
  10. 英飞凌 DAVE™ 4.1.2 SDK 开发app学习笔记——什么是DAVE APP?