数据结构和算法本质就是帮我们用最快的时间和最少的空间来执行我们的代码。所以,执行效率是衡量一个算法的非常重要的指标。那如何来计算你的算法代码的执行效率呢?这就需要时间、空间复杂度来分析了。

有人可能会说,我把代码执行一遍,然后通过统计、监控就能知道执行的时间和需要的内存大小。干嘛还需要时间、空间复杂度来分析呢?我都能得到具体需要的时间和内存了,还需要多此一举吗?

首先,这种评估算法效率的方法没有问题,我们还给这种方法起了一个名字,叫事后统计法。但是这种方法有很大的局限性。

1. 测试结果受测试环境影响

测试环境的硬件对测试结果有非常大的影响。比如,同样的代码在i7和i5的机器上执行,结果肯定是不同的。还有可能在一台机器上A代码比B代码执行速度要快,我们换另外一台机器却得到相反的结果。

2. 测试结果受数据规模的影响

比如排序算法,原始数据如果有序度不一样,执行的时间就会有很大的差别。原始数据规模的大小不同,也可能会让原来速度快的算法变成速度慢的。

所以我们就需要一个不需要具体的测试数据来测试,就可以大概估算出执行效率的方法,就是时间、空间复杂度分析方法。

大O复杂度表示方法

我们通过度代码,来估算出它执行所需要的时间,下边来看一段具体的代码。

public int Function(int n){ int sum = 0; for(int i = 1; i <= n; i++) { sum += i; } return sum;}

这里我们假设每一行代码执行的时间都是相同的为 t,那么第 3 行执行的时间为 t,第 4 和 6 行执行了 n 次,需要时间为 2nt,总的时间为 (1+2n)t,可以看出来总的代码的执行时间 T(n) 与每行代码的执行次数成正比。

然后我们再来看下边的代码

public int Function(int n){ int sum = 0; for(int i = 1; i <= n; i++) { for(int j = 1; j <= n; j++ { sum += i*j; } } return sum;}

这段代码中在上边的基础上又套了一层 for 循环,第 6 和 8 行执行了 n^2 次,需要的时间为 2n^2 * t ,总的需要的时间为 T(n)=(2n^2+2n+1) * t

通过上述两个具体的代码例子我们总结出一个公式:


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


T(n) 表示代买执行的时间,n 是数据的大小,f(n) 表示代码执行的总次数,O 表示公式中 T(n) 与 f(n) 成正比。这就是大 O 时间复杂度表示法,它实际上并不表示代码具体执行所需要的时间,它表示随着数据规模的变化代码执行时间的变化趋势。

当 n 非常大时,低阶、系数、常量对结果的影响就非常小了,所以我们可以把这几项忽略不记,只保留最高阶的就可以了,所以上边两个例子中 O(1+2n) 就可以记为 O(n),o(2n^2+2n+1) 就可以记为 O(n^2)。

上边我们知道了怎么用大 O 时间复杂度的表示方法。那么我们如何具体分析一段代码的时间复杂度呢?

  • 只关注循环次数最多的一段代码

因为大 O 时间复杂度只表示一种变化的趋势,所以我们只需要关心阶数最高的那部分就可以了,低阶、系数、常量我们都可以忽略。以上边第一段代码为例 O(1+2n),我们忽略掉系数和常量最后就得到了 O(n)。

  • 加法法则

对于顺序执行的长代码,我们把它分成几部分,分别求出其总时间 T(n) ,然后相加得到总的时间,最后同样忽略低阶、系数、常量部分,保留最高阶的部分然后得出最后的时间复杂度大 O。

  • 乘法法则

对于逻辑复杂的嵌套代码,我们分别求嵌套内外代码的复杂度,然后相乘得出最终的时间复杂度大 O。

几种常见的时间复杂度分析

下边列举出常见的时间复杂度量级

对于非多项式量级的算法会随着数据规模的增大急剧增加,所以分多项式量级的算法是非常低效的,我们不做过多的介绍。主要来介绍几种常见的多项式量级的时间复杂度。

  1. 常数阶 O(1)

O(1) 只是常量级时间复杂度的表示方式,不是只有一行代码,而是每一段代码的执行时间不随着 n 的数据规模的变大而变长,这样的代码的时间复杂度记为 O(n)。

  1. 对数阶 O(logn) O(nlogn)

对数阶复杂度很常见,但是分析的时候却不容易,下面我们用一段实际的例子来看看对数阶时间复杂度。

public void Function(int n){ int i = 1; while(i<=n) { i = i*2; }}

通过上边我们总结的方法,我们只需要知道 while 循环的次数,就能得到这段代码的复杂度。从代码中可以看出 i 的值从 1 开始,每循环一次乘以 2,直到 i 的值大于 n 的时候结束,我们得到规律然后把结果列出来,

2^0 2^1 2^3 2^4 …… 2^x = n ,然后求得执行的次数 x = logn ,这段代码的时间复杂度就是 O(logn)。

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

我们再来讲一种跟前面都不一样的时间复杂度,代码的复杂度由两个数据的规模决定,所以我们需要同时考虑两种数据规模对结果的影响,如果是顺序的,那么时间复杂度就为 O(n+m),如果为嵌套的那么时间复杂度为 O(n*m)。

空间复杂度分析

理解了上边的时间复杂度的分析方法,空间复杂度的分析也就很简单了。空间复杂度表示算法的存储空间与数据规模之间的增长关系。

同样我们通过一段实际的代码来分析一下。

public void Function(int n){ int i = 0; int[] a = new int[n]; for(i;i

我们看到第 3 行代码,我们申请了一个空间存储变量 i ,但是这个是常数阶的,不会随 n 的变化而变化,所以可以忽略,第 4 行我们申请了一个大小为 n 的 int 类型数组,除此之外其余代码没有占用其他的空间,所以这段代码的空间复杂度为 O(n)。

我们常见的空间复杂度有 O(1)、O(n)、O(n^2),对数阶的空间复杂度一般情况下用不到。所以空间复杂度比时间复杂度容易分析的多,我们也只需要掌握常见的几种就可以了。

最后我们总结一下常见的几种复杂度,执行效率从高到低依次为

O(1)>O(logn)>O(n)>o(nlogn)>O(n^2)

如果觉得对你有帮助,可以推荐和分享给你的朋友

欢迎关注公众号:「努力给自己看」

一层循环时间复杂度_数据结构与算法系列——时间、空间复杂度相关推荐

  1. a*算法的时间复杂度_数据结构与算法系列——时间、空间复杂度

    数据结构和算法本质就是帮我们用最快的时间和最少的空间来执行我们的代码.所以,执行效率是衡量一个算法的非常重要的指标.那如何来计算你的算法代码的执行效率呢?这就需要时间.空间复杂度来分析了. 有人可能会 ...

  2. 一层循环时间复杂度_数据结构:二叉排序树的前/中/后序遍历(递归与循环两种版本)...

    树的设计初衷与操作时间复杂度 树这种数据结构的出现主要是对链表数据结构的优化,链表数据结构是线性结构,操作一般需要O(N)的时间复杂度,树是链表的变形,即链表的每个节点包含一个节点,而树的节点可以包含 ...

  3. 数据结构与算法的时间空间复杂度

    提到数据结构与算法就不得不提时间复杂度和空间复杂度,本人看大部分文章介绍都比较晦涩难懂,就想着用简单的代码示例快速让你理解数据结构与算法的时间空间复杂度. 首先,时间复杂度表示的是使用某个数据结构或者 ...

  4. 数据结构排序算法实验报告_[数据结构与算法系列]排序算法(二)

    我的上一篇文章向大家介绍了排序算法中的冒泡排序.插入排序和选择排序.它们都是平均时间复杂度为 O(n^2) 的排序算法,同时还为大家讲解了什么是原地排序和什么是排序的稳定性.下图是这三种算法的比较,不 ...

  5. 一层循环时间复杂度_算法的时间与空间复杂度(一看就懂)

    算法(Algorithm)是指用来操作数据.解决程序问题的一组方法.对于同一个问题,使用不同的算法,也许最终得到的结果是一样的,但在过程中消耗的资源和时间却会有很大的区别. 那么我们应该如何去衡量不同 ...

  6. 假设有搅乱顺序的一群儿童成一个队列_数据结构与算法系列之栈amp;队列(GO)...

    以下完整代码均可从这里获取 栈 栈的基本概念 「后进先出.先进后出就是典型的栈结构」.栈可以理解成一种受了限制的线性表,插入和删除都只能从一端进行 当某个数据集合只涉及在一端插入和删除数据,并且满足后 ...

  7. 一层循环时间复杂度_渐进时间复杂度分析

    公众号:原与译 直接看题: 给定一个自然数 n,然后求出前 n 个自然数的和 sum.( n > 0 ) 如: n = 3,则 sum = 1 + 2 + 3 = 6 n = 5,则 sum = ...

  8. 高度平衡二叉树的构建_数据结构与算法系列(十六)平衡二叉树的构建实现过程演示...

    我们在上一篇文章中分享了平衡二叉树的定义和实现原理,这一节我们来演示如何通过代码实现平衡二叉树,最后分析下平衡二叉树的算法复杂度. 实例演示 在开始之前,我们先通过一个对比来加强理解,在没有介绍平衡二 ...

  9. 就地链表反转_数据结构与算法系列之链表操作全集(二)(GO)

    以下完整的代码,及测试代码均可从这里获取 https://github.com/Rain-Life/data-struct-by-go 常见的链表操作 单链表反转 方法一:就地反转法 思路 就地反转法 ...

最新文章

  1. 阿里云OSS图片上传类
  2. Java数组的十大方法
  3. Deep Learning(深度学习)学习笔记整理系列三
  4. 猎豹MFC--CMenu菜单 设置主菜单 给主对话框设置菜单 设置快捷菜单
  5. mysql error writing_MySQL:Error writing file (Errcode: 28)解决方法
  6. mysql 循环体 如何测试_mysql里如何循环插入数据,进行测试
  7. (Ajax)axios源码简析(三)——请求与取消请求
  8. ifeq makefile 或语句_学习笔记:Makefile的ifeq逻辑或,逻辑与的变通实现
  9. java中的mapper是什么_Java使用ObjectMapper的简单示例
  10. Android Studio 使用笔记:工具窗口浮动与布局恢复
  11. 嵌入式开发--Altuim Designer生成的PCB文件过大,及其他日常技巧
  12. U890采购入库单修改供应商
  13. 人工智能python编程训练营_贪心科技 人工智能 Python 编程特训营 第四个主题项目代码...
  14. 隧道点云处理(三):一种简单的隧道二维中线提取方法
  15. 【线性代数笔记】正定矩阵及其性质
  16. Android 之注册Facebook开发者账号
  17. 爱科赛博冲刺科创板:拟募资3.8亿 陕西集成电路与达晨是股东
  18. 新商业模式:在区块链上寻找新机会
  19. javaweb学生竞赛管理系统
  20. jop怎么读音英语怎么说_job是什么意思_ job的翻译_音标_读音_用法_例句_爱词霸在线词典...

热门文章

  1. Linux:Vim的安装与配置
  2. 奇讯新游 PHP,QXPLAY
  3. 路径规划之基于优化的规划算法
  4. haproxy配置代理tomcat和nginx_Nginx负载均衡配置实例
  5. 位平面提取 matlab,哪位高手知道图像位平面移位在Matlab中如何实现吗?[图像图形(图象)论坛]...
  6. python中碰撞的代码_Python…Tkinter碰撞
  7. AWT_addKeyListener键盘监听事件(Java)
  8. js保存网络图片至本地
  9. JS删除两个数组有相同元素或者相同属性
  10. PCL之积分图法线估计