算法的一个非常重要的的考量指标是执行效率,复杂度分析就是用来衡量代码执行效率的一种方法。前面又提到复杂度分析是数据结果和算法学习的精髓。
1. 实际的测试结果非常依赖测试环境
比如测试环境硬件配置不一样,得到的结果截然不同
2. 测试结果受数据规模的影响很大
比如排序算法,就会受实际测试数据的有序度和数据的规模影响。导致测试的结果无法反应算法的性能。
3. 可以开发阶段更好的指导代码的编写
复杂度分析可以估算代码的执行效率,从而在根据实际选择算法时起到一定的指导作用。
复杂度分析不需要具体测试数据测试,就可以大概估计算法执行效率。既快速方便,又不受测试环境的影响,所以我们需要复杂度分析。
复杂度分析包括时间复杂度分析和空间复杂度分析,那么如何进行复杂度分析呢?
如果我们将每行代码的执行时间看成固定的,那所有代码的执行时间 T(n) 与每行代码的执行次数成正比。我们再将每行代码的执行次数之和用f (n)表示,那就可以总结出一个公式:
T(n) = O(f(n))
其中n表示数据规模的大小,O代表T(n)与f(n)之间是正比关系。这就是大O时间复杂度表示法。
大O时间复杂度表示的是代码执行时间随数据规模增长的变化趋势。并不是正真的执行时间。当n很大时,公式中的低阶、常量、系数三部分对变化趋势影响不大,所以可以忽略,只记录最大量级的那个就可以了。
1. 单一循环看次数执行最多的
2. 如果代码只受单一数据规模n的影响,非嵌套循环相加取量级最大的
3. 如果代码受多个数据规模的影响,非嵌套循环相加取和
4. 嵌套循环内外相乘取乘积
常见的时间复杂度有:O(1)、O(logn)、O(n)、O(nlogn)、O( )。
此外还有:O(m+n)、O(m*n),前者为复杂度有两个数据规模决定,后者则是起决定性的两个数据规模是嵌套的。
由时间复杂度的表示意义可知,空间复杂度表示的是算法的存储空间随数据规模增长的变化趋势。
常见的空间复杂度有: O(1)、O(n)、O()。空间复杂度和时间复杂度类似,所以和数据规模n无关的相,我们都可以忽略。
练习一:

如上图一:函数test,有一个形参n,这个函数需要执行的代码为第4行、第5行,在调用函数test的过程中,第4行n代码是将n和5做了乘法,运行次数为1次,第5行代码为返回num的值,执行次数也为1次,根据大O复杂度表示法,可知f(n)为每行代码执行次数之和,所以这段代码的时间复杂度T(n)=O(1 + 1) = O(2),又因为时间复杂度研究的是代码执行时间随数据规模增长的趋势。可见,图一代码中每行代码的执行次数之和是一个常量,当n很大时,常量对变化趋势影响不大,所以可以忽略。这种代码执行时间为常量的时间复杂度都可以表示为O(1)。


再看图二、图三,虽然代码的行数变多了,但是通过分析可知,这几段代码中每行代码的执行次数之和都是常量,执行时间并不随数据规模n的增长而变化。所以他们的时间复杂度都是O(1)。
一般情况下,只要算法中不存在循环语句、递归语句,即使有成千上万行的代码,其时间复杂度也是O(1)。
练习二:

再看图四,分析可知第4行代码的执行次数是n次,第5行代码的执行次数也是n次,可得这段代码的时间复杂度T(n)=O(n + n)=O(2n)。我们将系数忽略,取最大两级的一个,得到T(n)=O(n)。所以这段代码的时间复杂度就是O(n)。这也验证了“单一循环看次数执行最多的行”的分析方法。
练习三:

再来看一个嵌套循环,如图五,分析可知第4行代码执行次数为n,第5行代码执行次数为n x n,第6行代码的执行次数为n x n。所以根据大O复杂度表示法可得这段代码的时间复杂度为:T(n)=O(n + nxn + nxn)=O(n+2)。又知低阶、系数可以忽略,这段代码的时间复杂度为:T(n)=O(
)。刚好验证了“嵌套循环内外相乘取乘积”的分析方法。
练习四:

如图六,根据单一循环看次数执行最多的行的分析方法,可知我们只要分析第5行代码或者第6行代码就可以了。代码中循环结束的条件是i>=n,但是i并不是每次递增1,i的变化是每次乘以2。假设第6行代码执行x次后循环结束,那么i的取值列出来就是, , , , ,,...,可以看出i的值为,x即为第6行代码执行的次数。也就是当
>= n时循环结束。那我们就可以近似的得出第6行代码的执行次数x=
,所以这段代码的时间复杂度T(n)=O(
)。那么当第6行代码变成i= i * 3或者i=i*10等的时候,那这段代码的时间复杂度就是O(
)、O(
)。不管是以哪个数字为底,我们都可以把这种对数阶的时间复杂度表示为O(logn)。所以图六代码的时间复杂度为T(n)=O(logn)。
练习五:

我们已经知道test函数这段代码的时间复杂度为O(logn),那test2这段代码是将test代码段嵌套在了一个for循环中,根据“嵌套循环内外相乘取乘积”的分析方法,可知for循环中test函数的执行次数为n,所以外部循环代码段的时间复杂度为O(n),又因为内部循环代码段的时间复杂度,也就是test代码段的时间复杂度为:O(logn),可得到test2代码段的时间复杂度T(n)=O(n)*O(logn)=O(nlogn)。
练习六:

前面的代码段都是只有一个参数n,图8中的test函数有两个形参m和n,再看函数体,第3、4行代码的执行次数受m的影响,第5、6行代码的执行次数受n的影响。即图8代码段的每行代码的执行次数之和受到了m和n两个数据规模的影响。这种情况下,m和n都不能确定是多少,所以都不能忽略。我们分析可知,第3、4行代码的时间复杂度T1(m)=O(m),第5、6行代码的时间复杂度T2(n)=O(n),所以根据“如果代码受多个数据规模的影响,非嵌套循环相加取和”的分析方法可得,这段代码的时间复杂度为:T(m)+T(n)=O(m)+O(n)=O(m+n)。
练习七:

图9代码段是一个嵌套循环,我们可以先将第4、5行代码段看成是一个单一循环,很容易可以得到它的时间复杂度T(n)=O(n),再看第3行代码,这是外部循环部分,这行代码的执行次数受m的影响,从而得到外部循环代码段的时间复杂度为T(m)=O(m),根据“嵌套循环内外相乘取乘积”的分析方法,可得test代码段的时间复杂度为:T(m)*T(n)=O(m)*O(n)=O(m*n)。
练习一:

图10中,第3行代码中,我们申请了一块空间a来存放数字4,第4行代码中我们又申请了一块空间sum来存放a+n的和。第5行代码并没有申请空间,只是返回了sum的值。由于空间复杂度表示的是算法的存储空间随数据规模增长的变化趋势,而经过我们分析,不管n的数据规模如何变化,这段代码永远只是申请了a和sum两块空间,并没有对存储空的的变化趋势造成影响,可见是常量阶的,所以这段代码的空间复杂度为:O(1)。

再来看图11,第3行代码中创建了一个list对象num_list,第4、5行代码中是循环三次,每次讲i*n的值存放到num_list对象中。由于num_list是一个可变对象,每存入一个数据就需要申请一块存储空间。但是由于第4行代码中,循环的次数是固定的3次,所以不管数据规模n如何变化,代码中只是申请了三次存储空间。也没有对存储空间的变化趋势造成影响,所以它的空间复杂度也是常量阶的,所以也是O(1)。
练习二:

图12和图11不同之处在于第4、5行代码的执行次数受n的数据规模的影响,我们知道num_list对象是一个列表,每放入一个数据都会申请一块空间存储,如果放入n个数据,那就要申请n块空间存储,所以这段代码的申请存储空间的次数或总量,会受到n的影响,所以可以得出这段代码的空间复杂度为:O(n)。

图13是在图12代码段的举出上又嵌套的一层循环,更具“嵌套循环内外相乘取乘积”的分析方法,可知,图13这段代码的空间复杂度为:O(n*n)=O()。
以上就是我对本节课程的理解,当然例子都是写的简单的例子。王争老师提到“复杂度分析并不难,关键在于多练。”,我在学习的时候,就是先听讲几遍,在动手写一下代码,试着分析一下复杂度。然后再和课程讲的核对下,看是不是一样,然后再多听几遍。这样使我印象更深刻。慢是慢了些,但相信对我而言应该是不错的学习方法。
以上可能有些理解的不到位,或是表达的不准,欢迎大家指正,帮助我更好的理解。
我想将html转换为纯文本。不过,我不想只删除标签,我想智能地保留尽可能多的格式。为插入换行符标签,检测段落并格式化它们等。输入非常简单,通常是格式良好的html(不是整个文档,只是一堆内容,通常没有anchor或图像)。我可以将几个正则表达式放在一起,让我达到80%,但我认为可能有一些现有的解决方案更智能。 最佳答案 首先,不要尝试为此使用正则表达式。很有可能你会想出一个脆弱/脆弱的解决方案,它会随着HTML的变化而崩溃,或者很难管理和维护。您可以使用Nokogiri快速解析HTML并提取文本:require'nokogiri'h
我主要使用Ruby来执行此操作,但到目前为止我的攻击计划如下:使用gemsrdf、rdf-rdfa和rdf-microdata或mida来解析给定任何URI的数据。我认为最好映射到像schema.org这样的统一模式,例如使用这个yaml文件,它试图描述数据词汇表和opengraph到schema.org之间的转换:#SchemaXtoschema.orgconversion#data-vocabularyDV:name:namestreet-address:streetAddressregion:addressRegionlocality:addressLocalityphoto:i
有时我需要处理键/值数据。我不喜欢使用数组,因为它们在大小上没有限制(很容易不小心添加超过2个项目,而且您最终需要稍后验证大小)。此外,0和1的索引变成了魔数(MagicNumber),并且在传达含义方面做得很差(“当我说0时,我的意思是head...”)。散列也不合适,因为可能会不小心添加额外的条目。我写了下面的类来解决这个问题:classPairattr_accessor:head,:taildefinitialize(h,t)@head,@tail=h,tendend它工作得很好并且解决了问题,但我很想知道:Ruby标准库是否已经带有这样一个类? 最佳
给定一个复杂的对象层次结构,幸运的是它不包含循环引用,我如何实现支持各种格式的序列化?我不是来讨论实际实现的。相反,我正在寻找可能会派上用场的设计模式提示。更准确地说:我正在使用Ruby,我想解析XML和JSON数据以构建复杂的对象层次结构。此外,应该可以将该层次结构序列化为JSON、XML和可能的HTML。我可以为此使用Builder模式吗?在任何提到的情况下,我都有某种结构化数据-无论是在内存中还是文本中-我想用它来构建其他东西。我认为将序列化逻辑与实际业务逻辑分开会很好,这样我以后就可以轻松支持多种XML格式。 最佳答案 我最
我正在尝试使用Curbgem执行以下POST以解析云curl-XPOST\-H"X-Parse-Application-Id:PARSE_APP_ID"\-H"X-Parse-REST-API-Key:PARSE_API_KEY"\-H"Content-Type:image/jpeg"\--data-binary'@myPicture.jpg'\https://api.parse.com/1/files/pic.jpg用这个:curl=Curl::Easy.new("https://api.parse.com/1/files/lion.jpg")curl.multipart_form_
无论您是想搭建桌面端、WEB端或者移动端APP应用,HOOPSPlatform组件都可以为您提供弹性的3D集成架构,同时,由工业领域3D技术专家组成的HOOPS技术团队也能为您提供技术支持服务。如果您的客户期望有一种在多个平台(桌面/WEB/APP,而且某些客户端是“瘦”客户端)快速、方便地将数据接入到3D应用系统的解决方案,并且当访问数据时,在各个平台上的性能和用户体验保持一致,HOOPSPlatform将帮助您完成。利用HOOPSPlatform,您可以开发在任何环境下的3D基础应用架构。HOOPSPlatform可以帮您打造3D创新型产品,HOOPSSDK包含的技术有:快速且准确的CAD
目录一.加解密算法数字签名对称加密DES(DataEncryptionStandard)3DES(TripleDES)AES(AdvancedEncryptionStandard)RSA加密法DSA(DigitalSignatureAlgorithm)ECC(EllipticCurvesCryptography)非对称加密签名与加密过程非对称加密的应用对称加密与非对称加密的结合二.数字证书图解一.加解密算法加密简单而言就是通过一种算法将明文信息转换成密文信息,信息的的接收方能够通过密钥对密文信息进行解密获得明文信息的过程。根据加解密的密钥是否相同,算法可以分为对称加密、非对称加密、对称加密和非
本教程将在Unity3D中混合Optitrack与数据手套的数据流,在人体运动的基础上,添加双手手指部分的运动。双手手背的角度仍由Optitrack提供,数据手套提供双手手指的角度。 01 客户端软件分别安装MotiveBody与MotionVenus并校准人体与数据手套。MotiveBodyMotionVenus数据手套使用、校准流程参照:https://gitee.com/foheart_1/foheart-h1-data-summary.git02 数据转发打开MotiveBody软件的Streaming,开始向Unity3D广播数据;MotionVenus中设置->选项选择Unit
文章目录一、概述简介原理模块二、配置Mysql使用版本环境要求1.操作系统2.mysql要求三、配置canal-server离线下载在线下载上传解压修改配置单机配置集群配置分库分表配置1.修改全局配置2.实例配置垂直分库水平分库3.修改group-instance.xml4.启动监听四、配置canal-adapter1修改启动配置2配置映射文件3启动ES数据同步查询所有订阅同步数据同步开关启动4.验证五、配置canal-admin一、概述简介canal是Alibaba旗下的一款开源项目,Java开发。基于数据库增量日志解析,提供增量数据订阅&消费。Git地址:https://github.co
我正在尝试在Rails上安装ruby,到目前为止一切都已安装,但是当我尝试使用rakedb:create创建数据库时,我收到一个奇怪的错误:dyld:lazysymbolbindingfailed:Symbolnotfound:_mysql_get_client_infoReferencedfrom:/Library/Ruby/Gems/1.8/gems/mysql2-0.3.11/lib/mysql2/mysql2.bundleExpectedin:flatnamespacedyld:Symbolnotfound:_mysql_get_client_infoReferencedf