玩转数据结构——均摊复杂度和防止复杂度的震荡(笔记)

数据规模

这里写图片描述

时间复杂度

并不是所有的双层循环都是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减半

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/448277.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

解决:bash: vim: command not found、docker 容器不识别 vi / vim 、docker 容器中安装 vim

前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到教程。 1. 在 Docker 容器中编辑文件&#xff0c;报错如下&#xff1a; bash: vim: command not found2. 安装 vim &#xff1a; apt-get in…

路考

路考基本项目组成 路考即是科目三&#xff0c;是新增加的一个考试项目&#xff0c;基本项目有13项&#xff0c;包括上车准备、起步、直线行驶、变更车道、通过路口、靠边停车、通过人行横道线、通过学校区域、通过公共汽车站、会车、超车、掉头、夜间行驶。 上车准备 …

OpenDDS通讯rtps_discovery对等发现模式的pub和sub匹配的日志

OpenDDS的通讯体系中&#xff0c;提供了丰富的日志输出&#xff0c;通过日志输出可以清晰的看到pub和sub方的主题匹配的过程&#xff0c;是加深对OpenDDS过程了解的一个好方法。 下面的日志&#xff0c;以OpenDDS3.8为基础&#xff0c;增加了部分日志和时间戳输出。 rtps_dis…

Developing Web Applications with Apache, MySQL, memcached, and Perl

Developing Web Applications with Apache, MySQL, memcached, and Perl转载于:https://www.cnblogs.com/gavinhughhu/archive/2009/11/02/1594290.html

awk 中 {print $1} 什么意思

前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到教程。 举个例子 echo "aa bb cc" | awk -F {print $1} 结果就是aa&#xff0c;意思是把字符串按空格分割&#xff0c;取第一个。aw…

有驾照不等于会开车,教你开车技巧27招

当今有车的人真的是越来越多了&#xff0c;不要以为自己有驾照就是会开车了哦&#xff0c;其实开车还是有很多技巧的。下面就跟小编看下学会那些招数才真算会开车吧。 1、上车先看车 上车前绕车转一圈&#xff0c;看车的外况、轮胎、车底下有没有漏油漏水。一个星期还得揭开盖子…

OpenDDS通讯中rtps_discovery对等发现的基本配置和说明

OpenDDS的对等发现模式中&#xff0c;可以采用组播或单播方式进行发现和基于主题的DataReader和DataWriter的匹配&#xff0c;下面是一个简单的配置样例&#xff1a; [common] DCPSGlobalTransportConfig$file ORBDebugLevel0 DCPSDebugLevel3 DCPSTransportDebugLevel0 ORBLo…

用户使用协议

知乎协议&#xff08;草案&#xff09; 欢迎您来到知乎。 请您仔细阅读以下条款&#xff0c;如果您对本协议的任何条款表示异议&#xff0c;您可以选择不进入知乎。当您注册成功&#xff0c;无论是进入知乎&#xff0c;还是在知乎上发布任何内容&#xff08;即「内容」&#xf…

解决: bash: unzip: command not found、linux 安装 zip 命令

前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到教程。 1. 执行解压命令报错&#xff1a; bash: unzip: command not found 2. 安装 zip&#xff1a; yum install -y unzip zip 3. 重试成功…

基于OpenDDS开发发布订阅HelloMsg程序的过程(Windows)

基于OpenDDS的应用开发&#xff0c;主要分两个部分的工作&#xff1a; &#xff08;1&#xff09;定义自己的IDL文件&#xff0c;并编译成消息数据类型通讯动态库&#xff1b; &#xff08;2&#xff09;分别编写pub和sub程序&#xff0c;运行 具体步骤&#xff0c;有以下几…

面试后的总结

面试中的收获&#xff1a; 优点&#xff1a; 1. 设计用例考虑较为全面。 2. 自动化&#xff0c;性能都有涉猎&#xff0c;但不深入。 3. 对业务理解较深入。 缺点&#xff1a; 1. 接口自动化停留在初级阶段。 2. UI自动化了解较少。 3. 性能压测缺少数据清洗等步骤。 4. 算法还…

怎样正确使用车灯?

当我们被对面来车明晃晃的远光灯照得意识模糊时&#xff0c;当你快速接近一辆摩托车却发现那是一辆坏了一盏尾灯的卡车时&#xff0c;或是当你前方的小车忽然亮起倒车灯却在往前行驶&#xff0c;最后意识到那只是因为刹车灯与倒车灯线路颠倒时&#xff0c;你就会发现在人们都认…

如何配置DDS以使用多个网络接口?How do I configure DDS to work with multiple network interfaces?

最近在使用OpenDDS的时候遇到一个问题&#xff1a;存在多个虚拟网卡时&#xff0c;发布&#xff08;订阅&#xff09;端重新连接时会阻塞几分钟&#xff0c;在外网找到一篇与此相关的文章。 You cannot specify which NICs DDS will use to send data. You can restrict the NI…

oracle赋予一个用户查询另一个用户中所有表

说明&#xff1a;让用户selame能够查询用户ame中的所有表&#xff08;不能添加和删除&#xff09;1.创建用户selamecreate user selame identified by Password;2.设置用户selame系统权限grant connect,resource to selame; 3.设置用户selame对象权限 grant select any table t…

使用可靠多播与OPENDDS进行数据分发

介绍 也许应用程序设计人员在创建分布式系统时面临的最关键决策之一是如何在感兴趣的各方之间交换数据。通常&#xff0c;这涉及选择一个或多个通信协议并确定向每个端点分派数据的最有效手段。实现较低级别的通信软件可能是耗时的&#xff0c;昂贵的并且容易出错。很多时候&a…

考试 驾校

您的孩子在车里安全么&#xff1f;儿童座椅那点事儿 儿童安全座椅用最最普通的话来解释就是一种系于汽车座位上,供小童乘坐,有束缚设备,并能在发生车祸时,束缚着小童以保障小童安全的座椅。 儿童安全座椅在欧美发达国家已经得到了普遍使用&#xff0c;这些国家基本上都制定了相…

margin为负值的几种情况

1、margin-top为负值像素 margin-top为负值像素&#xff0c;偏移值相对于自身&#xff0c;其后元素受影响&#xff0c;见如下代码&#xff1a; 1 <!DOCTYPE html>2 <html lang"zh">3 <head>4 <meta charset"UTF-8" />5 &l…

事件EVENT,WaitForSingleObject(),WaitForMultipleObjecct()和SignalObjectAndWait() 的使用(上)

用户模式的线程同步机制效率高&#xff0c;如果需要考虑线程同步问题&#xff0c;应该首先考虑用户模式的线程同步方法。但是&#xff0c;用户模式的线程同步有限制&#xff0c;对于多个进程之间的线程同步&#xff0c;用户模式的线程同步方法无能为力。这时&#xff0c;只能考…

axios 中文文档、使用说明

以下内容全文转自 Axios 文档&#xff1a;https://www.kancloud.cn/yunye/axios/234845 ##Axios Axios 是一个基于 promise 的 HTTP 库&#xff0c;可以用在浏览器和 node.js 中。 Features 从浏览器中创建 XMLHttpRequests从 node.js 创建 http 请求支持 Promise API拦截请…

汽车熄火是什么原因?

汽车熄火是什么原因&#xff1f; 近来看见很多车主被车子熄火所困扰&#xff0c;驾校一点通帮助您从以下也许可以找出原因。 1、自动档车型&#xff1a; 自动档的车型不会轻易出现熄火的现象&#xff0c;而手动档的车型由于驾驶水平不高&#xff0c;可能会经常出现熄火的现象。…