[转帖]到底什么是时间复杂度

大学的时候  专业课 讲这个东西了 但是 自己一直没有仔细去学习..

到现在也不是很清晰..感觉自己对数学里面的对数 指数 还有离散数学 学习的不好

影响自己对程序世界的理解.

需要找时间 仔细学习 再翻翻. 

https://www.cnblogs.com/fanyi0922/p/10779471.html

我们常常在武侠小说中看到一位内力精深的高手在学习新的招式的时候修炼速度异常惊人,我心目中最经典的片段就是倚天屠龙记中张无忌学习乾坤大挪移和太极拳的时候了,他能在极短的时间内领会常人数十年所不能掌握的东西,即使拍了很多版本,每次看到这,我都大呼过瘾,仍然看的津津有味~

数据结构和算法对于程序员来说就像是武侠世界中江湖人士的内功心法,其重要程度不言而喻,而开启数据结构与算法历练之路大门的钥匙则是复杂度的分析,这里的复杂度主要指的就是时间复杂度。

数据结构与算法需要掌握的知识很多,后来经过大牛们的归纳总结提炼出图中 10 种数据结构与 10 种常用的算法,只需要掌握下面这张图我们日常工作中就可以游刃有余了:

聪明的同学会发现其实图中知识点还是很多的,看着少是因为没有展开脑图而已 ,要掌握的知识多是好事,说明我们进步的空间很大,学习之路可能很远,没关系,慢慢来,我们来日方长~

铺垫了这么多,相信大家对数据结构与算法也有了一些认识,我目前也是一名小白,期望通过每次的分享能够在数据结构与算法的道路上走的更远一些。

下面我们开始入门第一课 :时间复杂度的分析

主要包括以下 4 点:

  • 大O复杂度表示法
  • 常用的时间复杂度表示
  • 最好、最坏、平均、均摊时间复杂度
  • 空间复杂度

在一些面试题当中经常会出现对某一算法进行时间复杂度分析,在给出的选项中会有类似 O(1),O(n),O(logn)....的写法,那么像这样的O()的写法是什么意思呢?

这就要提到时间复杂度分析常用的 大O复杂度表示法。

 

  • 大O复杂度

 

大O复杂度实际上并不具体代表代码真正的执行时间,而是表示代码执行时间随数据规模增长的变化趋势,也叫渐进时间复杂度,简称为时间复杂度

看下面一个例子:

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

对上述代码而言,假设每一行代码的执行时间都是相同的记为 time(time 为常量),第2-4 行代码都是执行一次,各消耗时间为 time,第5、6行代码各执行 n 次,各消耗时间为 n * time,第7、8 行代码码各执行 n*n 次,各消耗时间为 n*n * time,所以上述代码的总消耗时间为:

2*n*n*time + 2*n*time+3*time = (2n²+2n+3)*time

用大 O 表示法则记为 O((2n²+2n+3)* time), 由于 time为常量,n为变量,即原式可以化简为 O(2n²+2n+3)。

当n很大时,甚至可以认为它趋近于无穷大时,根据极限的知识我们可以认为 O(2n²+2n+3) 中低阶、常量、系数三部分并不左右增长趋势,所以可以忽略,只用记录最高阶就可以了,即 O(2n²+2n+3) 可以写成 O(n²),这也就是上述代码的时间渐进复杂度,简称时间复杂度

由上面的例子可以看出,其实在分析时间复杂度的时候,我们只要关心阶数最高或者说是循环次数最多的一段代码就可以了,因为我们一般会忽略低阶、常量、系数这三部分。

时间复杂度常用到的另外2个法则是:加法法则和乘法法则,都比较简单,这里就不在多说了。

  • 常用的时间复杂度表示

O(1) , O(logn) , O(n) , O(nlogn) , O(n²),O(n³),O(2^n) ,O(n!),从左到右时间复杂度依次递增

  • O(1)

O(1) 表示常量阶,并不是说只执行了一行代码,只要代码的执行时间不随着 n 的增大而增大就可以定为常量阶,哪怕有成千上万行代码。另外如果有循环次数是常量的循环也定义常量阶。

  • O(logn) 、O(nlogn)

这种对数阶时间复杂度也是比较常见的。

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

从代码中可以看出 i 是成倍往上增长的,当 i 大于 n 时,循环就会结束,这其实是一道很简单的对数题:

2^x = n, 求 x 的值

我们都知道 x = log2 n (以 2 为底 n 的对数),那时间复杂度为什么不写成 O(log2 n )呢?

其实写成O(log2 n )也并没有错,如果我们把上述代码第4行 改成 i = i * 3,那是不是要写成 O(log3 n )了,显然不是,这样写虽然不错但是太麻烦了。

由我们仅存的高中数学知识可知,对数是可以相互转化的 :

log3n = log32 * log2n,log32为常数

那么,O(log3n) = O (log32 * log2n)= O(log2n),所以在对数时间复杂度中,就可以忽略对数的底,统一标识为 O(logn)

而 nO(logn) 就显而易见了,根据乘法法则,在外层再套一层时间复杂度为 O (n)的循环,上述代码复杂度就是 nO(logn) 了。

归并排序、快速排序的时间复杂度都是O(nlogn)。

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

在了解常用的复杂度后,我们在深入一层,之前的代码都比较简单,不需要考虑相应的情况,下面我们看一个比较复杂的例子:

//数组中查找变量 target 的位置,有则返回下标,没有则返回1int find(int[] array, int n, int target) {  int i = 0;  int pos = -1;  for (; i < n; ++i) { // n表示数组array的长度    if (array[i] == target) {        pos = i;        break;      }  }  return pos;}

上面这段代码的时间复杂度是多少呢?

这个时候我们可能会有这样的疑问:

目标值在不在数组中,如果不在怎么办,如果在,那具体在哪个位置呢?

这里我们如果再用之前的方法分析,结果就会有偏差了,因为代码中的循环是有可能被中断的(当找到目标值后 break)此时引入最好时间复杂度、最坏时间复杂度、平均时间复杂度的概念了。

顾名思义,最好时间复杂度就是最理想的情况下,也就是目标值就是数组的第一个元素,此时对应的时间复杂度为 O(1)

最坏时间复杂度就是最差的情况下,也就是说目标值不在数组中(或目标值在数组的末尾),此时需要循环n次中才能知道目标值是否在数组中,对应时间复杂度为O(n)。

  • 平均时间复杂度

最好和最坏时间复杂度其实都是极特殊的情况,为了更好的解释平均时间复杂度需要引入一个概念:平均情况时间复杂度,后面简称为平均时间复杂度

所谓的平均情况与求平均值类似,上述的寻找目标值在数组中的位置,一共有n+1 中情况,包括在数组 0 ~ n-1 的任一下标上 和不在数组中的情况,把需要查找元素的个数累加起来,再除以 n+1 ,就可以得到遍历元素的平均值:

(1+2+3+4……+n+n)/(n+1) = n(n+3)/2(n+1)

将O (n(n+3)/2(n+1)) 根据上述规则转换后,可以得出平均时间复杂度为 O(n)。

  • 加权平均时间复杂度 

我们虽然得出了结果,但是仔细一想这个结果好像并不准确,原因在于 这 n+1 种情况出现的概率其实是不同的,而且目标值出现在数组中某一位置的概率也是不同的。

为了方便计算,我们假定目标值出现在数组中与不在数组中的概率是相等的,都为 1/2 ;目标值出现在数组中某一位置的概率也是相等的,都为 1/n,根据乘法法则,我们要找的目标值出现在数组中的概率应该为 (1/2) * (1/n), 1/(2n)。

所以前面的计算最大的问题是没有考虑概率问题,将概率添加上的算式为:

((1+2+3+4……+n)*(1/2n)+ n*(1/2) ) = (3n+1)/4

这个值就是概率论中的加权平均值,也叫作期望值,所以平均时间复杂度的全称应该叫加权平均时间复杂度或者期望时间复杂度。

实际上一般情况下我们并不区分最好、最差、平均时间复杂度这三种情况。使用最开始的一个复杂度就可以满足需求了。

如果出现一块代码在不同情况下,时间复杂度有重量级差距,才会使用这三种复杂度来区分。

  • 均摊时间复杂度

均摊时间复杂度应用场景比较特殊,所以我们并不会经常用到。

均摊时间复杂度的主要思想是:

对一个数据结构进行一组连续操作中,大部分情况下时间复杂度都很低,只有个别情况下时间复杂度比较高,而且这些操作之间存在前后连贯的时序关系,这个时候,我们就可以将这一组操作放在一块儿分析,看是否能将较高时间复杂度那次操作的耗时,平摊到其他那些时间复杂度比较低的操作上。而且,在能够应用均摊时间复杂度分析的场合,一般均摊时间复杂度就等于最好情况时间复杂度 。

  • 空间复杂度

在了解了时间复杂度后,最后再补充一下空间复杂度,其实空间复杂度很简单,它表示算法的存储空间与时间的增长关系。

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

通过今天的分享,我们主要了解了数据结构与算法的重要性,与时间复杂度相关的一些知识,之后我们会继续学习数据结构与算法相关的知识,一起修炼内功,成为“江湖中的大侠”。

原文地址:https://www.cnblogs.com/jinanxiaolaohu/p/10789439.html

时间: 2024-10-31 08:07:21

[转帖]到底什么是时间复杂度的相关文章

网易云音乐如何从0到亿级用户整理笔记

为什么要做网易云音乐? l  老板是发烧友 l  市面音乐不喜欢,市面上音乐质量比较匮乏 l  做这件事对音乐行业有啥帮助,对公司有啥帮助,对用户有啥帮助 它是如何做出来的? 好口碑是如何打造的? 主要从互联网音乐市场的现状分析.如何做产品定位.如何跨越鸿沟.探索过程中用到哪些手段.需求挖掘与用户引导五个方面来解析 互联网音乐市场的现状分析: 主流:当时主流市场是酷狗,QQ,酷我: 第二市场是百度,天天动听,虾米,豆瓣fm, 多米,jinfm等 缺乏创新的大市场:主流市场是曲库型产品, 播放器型

死磕 java集合之TreeMap源码分析(四)-内含彩蛋

欢迎关注我的公众号"彤哥读源码",查看更多源码系列文章, 与彤哥一起畅游源码的海洋. 二叉树的遍历 我们知道二叉查找树的遍历有前序遍历.中序遍历.后序遍历. (1)前序遍历,先遍历我,再遍历我的左子节点,最后遍历我的右子节点: (2)中序遍历,先遍历我的左子节点,再遍历我,最后遍历我的右子节点: (3)后序遍历,先遍历我的左子节点,再遍历我的右子节点,最后遍历我: 这里的前中后都是以"我"的顺序为准的,我在前就是前序遍历,我在中就是中序遍历,我在后就是后序遍历. 下

各种时间复杂度到底差别有多大(有图有真相)

做算法分析的时候经常用到各种时间复杂度如O(n), O(logn), O(nlogn), O(n^2), ... 它们之间到底有多大的差别呢?下面这张图是一个直观的表达: 放大来看logn, n, 和nlogn的情况: 可见,如果我们能将时间复杂度从从O(n^2)减到到O(n),或从从O(n)减到到O(logn),都是性能上一个大的飞跃. 从另一个角度而言,大于O(n^2)或O(n^3)时间复杂度的程序实际上都是不可用的.根据维基百科,现在最强的CPU每秒大概可执行428亿条指令(4*10^10

排序算法到底能不能突破nlog(n)时间复杂度?

今天在刷算法意外发现排序算法通过二分查找改进可以得到log2(n!)的时间复杂度. 先看张各个时间复杂度的图形. 这是使用desmos画出来的图形.主要对比xlog(x), x^2, log(x!), log(x), x的图形. 再上张大点图片 通过图形对比log(x!)低于xlog(x)高于x,但通常我们的排序算法快排和归并的最优是xlog(x)最坏是n^2, 通过二分查找改进的排序算法最坏是log(n!),最好是n. 虽然nlog(n)和log(n!)相差不是特别大,我们可以看到当x=120

[转帖]“剖开” LinuxONE 和 Exadata,架构专家解读里面到底有什么

"剖开" LinuxONE 和 Exadata,架构专家解读里面到底有什么 http://server.zhiding.cn/server/2018/0914/3111044.shtml 说起IBM的LinuxONE以及Oracle的Exadata,相信在IT行业从事基础架构工作的同业们都不陌生.最直观的印象就是:它们都是大型服务器,体积非常庞大,价格非常昂贵,一个是IBM的拳头产品,一个是Oracle的拳头产品. 作者:赵海 来源:至顶网服务器频道[原创]2018-09-14 09:

[转帖]建一个5G基站,到底要花多少钱?

建一个5G基站,到底要花多少钱? http://www.itpub.net/2019/12/24/4925/ 自从国内5G正式宣布商用之后,全国各地的5G网络建设速度明显加快了. 5G基站的身影,出现在越来越多的城市.角落.5G信号的覆盖范围,也在不断扩大. 这意味着,5G的投资已经全面启动,并且在不断增加.一直以来,“5G究竟要花多少钱”,是人们普遍关心的话题. 有人说,5G的投资将会是4G的2~3倍.也有人说,5G的总投资将到达惊人的1.5万亿元. 根据最新的<2020中国5G经济报告>,

[转帖]JPA和Hibernate到底是什么关系???

JPA和Hibernate到底是什么关系??? https://www.cnblogs.com/mosoner/p/9494250.html (文章借用了其他几篇博客中的内容,因为是初学者,许多概念性的关系自己不能完全理解,就将大神的搬了过来,如有不当,可留言,本人自会妥善处理,谢谢) 在学习框架的过程中,发现学的东西很多,但是感觉他们之间的联系区别都不是很了解,知道JPA可以去实现持久化数据到数据库当中,Hibernate也有这样的功能,总以为他们之间是一种平级的关系,拥有同样的作用,是一种可

2016百度之星总结帖

2016百度之星总结帖 测试赛 选的2015资格赛的部分题目,第二题字符串处理,第三题map计数 1001 大搬家 f f (x) = x 两次置换后回到原位 dp a->b && b->a,考虑n个数 如果它独自成对,那么就有s[n-1]: 如果它与前面某个成对,首先可以有n-1个可取,然后每个都有s[n-2]: 故s[n] = s[n-1] + (n-1)s[n-2]; 1004 放盘子 今天他向来访者们提出一个恶俗的游戏.他和来访者们轮流往一个正多边形内放盘子.最后放盘子

实用科普帖!无线路由器1/2/3根天线有啥区别?

“天线越多覆盖越广,天线越多信号越强,总之天线越多的无线路由器就越好.” ——觉得很“常识”的朋友可以继续往下看正文了,觉得这种话题弱爆了.小编是那个什么的估计也不会点进来.还是那句话,我们的干货帖大多数是为了扫盲,欢迎各位大神补充.指正…… 首先,大家也应该注意到了,老一代无线路由器的天线肯定不会超过一根.这里的“老一代”指的是802.11n协议以前的802.11a/b/g路由,老的54M产品就只有一根天线. 这样的话,802.11n显然成了一条分水岭,也是从那时开始天线不再只有孤零零的一根(