玩转数据结构——均摊复杂度和防止复杂度的震荡(笔记)
数据规模
时间复杂度
并不是所有的双层循环都是O(n^2)的
复杂度实验来确定复杂度
// O(N) 两倍增加
int findMax( int arr[], int n ){assert( n > 0 );int res = arr[0];for( int i = 1 ; i < n ; i ++ )if( arr[i] > res )res = arr[i];return res;}
随后,O(n^2),数据规模乘二,时间复杂度乘4……
随着数据的增加,可以看到O(logN)
递归算法时间复杂度分析
不是有递归的函数就一定是O(nlogn)
深入:主定理
resize的复杂度分析——均摊复杂度 amortized time complexity
均摊分析和平均情况时间复杂度,前者是一个序列的操作取平均值,后者是针对不同输入来计算平均值
动态数组(Vector)每一个操作增加一个元素,删除一个元素相应的复杂度,就需要Amortized Time
动态栈,动态队列类似(数组)
对于添加操作来说,最坏的情况是addLast(e)的时候,也需要进行resize,那么复杂度就是O(n)级别的了。但是我们忽略了个问题:我们根本不可能每次操作的时候都会触发resize,因此我们使用最坏的情况分析添加操作的时间复杂度是不合理的
17次基本操作包含了9次添加操作 + 8次元素转移操作
平均,每次addLast操作,进行2次基本操作( 17/9 约等于2 )
假设capacity=n,n+1次addLast,触发resize,总共进行2n+1次基本操作
平均,每次addLast操作,进行2次基本操作( 2n+1/n+1 约等于 2 )
将1次resize的时间平摊给了n+1次addLast的时间,于是得到了平均每次addLast操作进行2次基本操作的结论
这样均摊计算,时间复杂度是O(1)级别的,这和我们数组中有多少个元素是没有关系的
在这个例子里,这样均摊计算,比计算最坏情况是有意义的,这是因为最坏的情况是不会每次都出现的。
关于均摊复杂度,其实在很多算法书中都不会进行介绍,但是在实际工程中,这样的一个思想是蛮有意义的:就是一个相对比较耗时的操作,如果我们能保证他不会每次都被触发的话,那么这个相对比较耗时的操作它相应的时间是可以分摊到其它的操作中来的。
同理,我们看removeLast操作,均摊复杂度也为O(1)
resize的复杂度分析——复杂度震荡
但是,当我们同时看addLast和removeLast操作的时候:
假设我们现在有一个数组,这个数组的容量为n,并且现在也装满了元素,那么现在我们再调用一下addLast操作,显然在添加一个新的元素的时候会需要扩容(扩容会耗费O(N)的时间),之后我们马上进行removeLast操作(根据我们之前的逻辑,在上一个操作里通过扩容,容量变为了2n,在我们删除1个元素之后,元素又变为了n = 2n/2,根据我们代码中的逻辑,会触发缩容的操作,同样耗费了O(n)的时间);那么我们如果再addLast、removeLast…等相继依次操作
对于addLast和removeLast来说,都是每隔n次操作都会触发resize,而不会每次都触发
但是现在我们制造了一种情景:同时看addLast和removeLast的时候,每一次都会耗费O(n)的复杂度,那么这就是复杂度的震荡。
resize的复杂度分析——出现复杂度震荡的原因及解决方案
removeLast时resize过于着急(采用了Eager的策略: 一旦我们的元素变为当前容积的1/2的时候,我们马上就把当前的容积也缩容为1/2)
解决方案: Lazy (在线段树中,也会用到类似的思路)
当元素变为当前容积的1/2时,不着急把当前容积缩容,而是等等;如果后面一直有删除操作的话,当删除元素到整个数组容积的1/4时,那么这样看来我们的数组确实用不了这么大的容积,此时我们再来进行缩容,缩容整个数组的1/2(这样,即便我们要添加元素,也不需要马上触发扩容操作)
当 size == capacity / 4时,才将capacity减半
玩转数据结构——均摊复杂度和防止复杂度的震荡(笔记)相关推荐
- 算法复杂度分析(下):最好、最坏、平均、均摊等时间复杂度概述
细化时间复杂度分析 代码千千万,有些代码逻辑会很复杂,所以为了更细化的分析算法的复杂度,再复杂度分析方面引入了4个知识点: 1.最好情况时间复杂度(best case time complexity) ...
- 3.最好、最坏、平均、均摊时间复杂度
关注公众号 MageByte,设置星标点「在看」是我们创造好文的动力.后台回复 "加群" 进入技术交流群获更多技术成长. 本文来自 MageByte-青叶编写 上次我们说过 时间复 ...
- 3L-最好、最坏、平均、均摊时间复杂度
关注公众号 MageByte,设置星标点「在看」是我们创造好文的动力.后台回复 "加群" 进入技术交流群获更多技术成长. 本文来自 MageByte-青叶编写 上次我们说过 时间复 ...
- 【数据结构与算法-java实现】二 复杂度分析(下):最好、最坏、平均、均摊时间复杂度的概念
上一篇文章学习了:如何分析.统计算法的执行效率和资源消耗? 点击链接查看上一篇文章:复杂度分析上 今天的文章学习以下内容: 最好情况时间复杂度 最坏情况时间复杂度 平均情况时间复杂度 均摊时间复杂度 ...
- 04 | 复杂度分析(下):浅析最好、最坏、平均、均摊时间复杂度
// n表示数组array的长度 int find(int[] array, int n, int x) {int i = 0;int pos = -1;for (; i < n; ++i) { ...
- 数据结构与算法---均摊时间复杂度
数据结构与算法-均摊时间复杂度 均摊时间复杂度,听起来可能和平均时间复杂度.但却不是,平均时间复杂度和均摊时间复杂度是两种分析时间复杂度的方法. 上代码!!! // array 表示一个长度为 n 的 ...
- 第3课:算法复杂度分析(下):最好、最坏、平均、均摊时间复杂度
目录 最好.最坏时间复杂度 平均情况时间复杂度 均摊时间复杂度 小结 最好.最坏时间复杂度 我们先看一个例子: /*例1:查找x在数组中出现的位置,如果没有找到,返回-1.n表示数组array的长度 ...
- 算法复杂度((平均,最好,最坏,均摊)时间复杂度,空间复杂度)
文章目录 前言 时间&空间复杂度 时间复杂度 1.最好情况时间复杂度(best case time complexity) 2.最坏情况时间复杂度(worst case time comple ...
- 算法笔记(一):复杂度分析:最好、最坏、平均、均摊
数据结构指的是"一组数据的存储结构", 算法指的是"操作数据的一组方法". 数据结构是为算法服务的,算法是要作用再特定的数据结构上的. 效率和资源消耗的度量衡- ...
最新文章
- 从“小”培养AI安全意识:OpenAI开源具有安全约束的RL训练工具
- java 遍历file_JAVA File类(文件的遍历,创建,删除)
- java异步调用数据库存储过程详解,java中如何调用存储过程
- rpm如何卸载mysql_Linux下卸载和安装MySQL[rpm包]
- dbscan用 java代码_聚类算法之DBScan(Java实现)[转]
- AWS:避免那些“神圣的法案”时刻的一些技巧
- 使用不可序列化的属性序列化Java对象
- 简约好看的域名售卖页html源码
- 信安精品课:第7章访问控制技术原理与应用精讲笔记
- 如何用5年时间从菜鸟成长为技术总监?
- 超强整理-计量面板数据分析资料大全
- 计算机网络与通信技术教案,计算机网络技术教案
- Miracle密码算法开源库(二)源码分析 :mralloc.c、mrarth0.c
- 【测验6 编程题】: 组合数据类型 (第6周)
- 将Python代码打包成Windows 10的可执行文件
- 从管好事提升管理水平--创建事
- [Jule CTF 2022] 部分WP
- 编程语言培训学哪个?
- linux系统中开机自启的三种方式
- 沈丘县司法局法治进校园金秋第一堂法治课
热门文章
- php怎么添加验证码,PHP添加验证码以及使用
- java map统计学生名单_Java含自己的总结:集合,学生,遍历,ArrayList,Set,Map,泛型,班级,发牌—诗书画唱...
- python中with open写csv文件_Python中的CSV文件使用with语句的方式详解
- 6 rethad 自定义硬盘_图文详解zabbix配置自定义监控项过程
- 手机游戏降低游戏延迟的软件_怎么降低手机网络延迟(减少网络延迟的5个小技巧)...
- redis——数据结构(字典、链表、字符串)
- cmake生成Win64位工程
- Projection投影
- html一个页面同时加载多个饼图,Html5饼图绘制实现统计图的方法
- C语言 项目练习-家庭收支软件