原文地址:https://rob-bell.net/2009/06/a-beginners-guide-to-big-o-notation/
计算机科学中,大O表示法被用来描述一个算法的性能或复杂度。大O表示法可以用来描述一个算法的最差情况,或者一个算法执行的耗时或占用空间(例如内存或磁盘占用)。
相信许多人读过《Programming Pearls》(《编程珠玑》)或者其他计算机科学书籍时,在看到大O符号或者其他奇怪的语法符号时都会感觉到自己遇到了一堵无法翻越的高墙。那这篇文章将会带领大家对大O表示法以及对数级算法有一个最简单的认识。
首先作为一个程序员,其次作为一个数学家,我(Rob Bell)发现透彻的理解大O表示法的最好方式就是来尝试一些代码示例。下面按照算法的增长级别,展示了一些常见的算法描述,同时针对每个算法给出了一个简单的示例。
O(1)表示该算法的执行时间(或执行时占用空间)总是为一个常量,不论输入的数据集是大是小。
bool IsFirstElementNull(IList<string> elements)
{
return elements[0] == null;
}
O(N)表示一个算法的性能会随着输入数据的大小变化而线性变化。下面的例子同时也表明了大O表示法其实是用来描述一个算法的最差情况的:在for循环中,一旦程序找到了输入数据中与第二个传入的string匹配时,程序就会提前退出,然而大O表示法却总是假定程序会运行到最差情况(在这个例子中,意味着大O会表示程序全部循环完成时的性能)。
bool ContainsValue(IList<string> elements, string value)
{
foreach (var element in elements)
{
if (element == value) return true;
}
return false;
}
O(N^2)表示一个算法的性能将会随着输入数据的增长而呈现出二次增长。最常见的算法就是对输入数据进行嵌套循环。如果嵌套层级不断深入的话,算法的性能将会变为O(N3),O(N4),以此类推。
bool ContainsDuplicates(IList<string> elements)
{
for (var outer = 0; outer < elements.Count; outer++)
{
for (var inner = 0; inner < elements.Count; inner++)
{
// Don't compare with self
if (outer == inner) continue;
if (elements[outer] == elements[inner]) return true;
}
}
return false;
}
O(2N)表示一个算法的性能将会随着输入数据的每次增加而增大两倍。O(2N)的增长曲线是一条爆炸式增长曲线——开始时较为平滑,但数据增长后曲线增长非常陡峭。一个典型的O(2^N)方法就是裴波那契数列的递归计算实现。
int Fibonacci(int number)
{
if (number <= 1) return number;
return Fibonacci(number - 2) + Fibonacci(number - 1);
}
要说明对数情况,稍稍有点复杂,因此我将使用一个非常通用的示例:
二分查找是一种用来在有序集合中进行查找的高效算法。二分查找从数据集的中间位置开始,然后用这个中间值和一个目标值进行比较。如果比较结果为相等,则程序返回成功。如果目标值大于中间值,程序会截取从中间值开始到最大值的那段数据集,并重复执行同样的查找方法。想死的,如果目标值小于中间值,程序将会继续在数据集中较小的那一半执行二分查找。二分查找程序会持续的将数据集对等分,以进入下一次循环,直到最终找到与目标值相等的数据后,程序就退出。
这类算法的性能就会被描述为O(logN)。正是通过这种不断对数据进行对等分的二分查找操作,使得二分查找算法的曲线从一个峰值开始,随着输入数据集的增长而慢慢的变得平缓。用例子来说明的话,例如一个包含10个输入数据的程序需要耗时一秒完成,则一个包含100个输入数据的程序就需要耗时两秒,然后一个包含1000个输入数据的程序就耗时三秒。加倍的输入数据对这类算法的性能结果影响非常小。基于如此,类似于二分查找的对数级算法在处理大量数据集时非常高效。
本文仅仅覆盖了关于大O表示法以及对数算法非常基本的知识概念。如果想要更深入的理解他们,可以参考维基百科:
大O表示法:https://en.wikipedia.org/wiki/Big_O_notation
对数:https://en.wikipedia.org/wiki/Logarithm
将一个整型的常量(字面值为int)赋给一个byte或者short类型的变量,只要不超过byte或short取值范围,就可以通过编译byte a = 1;//编译通过short b = 1;//编译通过将一个浮点型的常量(字面值的double)赋给一个float类型的变量,即使不超过float的取值范围,也会出现编译错误float c = 1.2;//编译报错因为1.2默认为double类型,而double的数据类型范围大于float数据类型的范围,所以编译出现错误!请问为什么Java中会有这种双_c++ double类型不可以赋值给float类型
Linux必学的60个命令Linux提供了大量的命令,利用它可以有效地完成大量的工 作,如磁盘操作、文件存Linux提供了大量的命令,利用它可以有效地完成大量的工作,如磁盘操作、文件存取、目录操作、进程管理、文件权限设定等。所以,在Linux系统上工作离不开使用系统提供的命令。要想真正理解Linux系统,就必须从Linux命令学起,通过基础的命令
卡拉兹(Callatz)猜想已经在1001中给出了描述。在这个题目里,情况稍微有些复杂。当我们验证卡拉兹猜想的时候,为了避免重复计算,可以记录下递推过程中遇到的每一个数。例如对n=3进行验证的时候,我们需要计算3、5、8、4、2、1,则当我们对n=5、8、4、2进行验证的时候,就可以直接判定卡拉兹猜想的真伪,而不需要重复计算,因为这4个数已经在验证3的时候遇到过了,我们称5、8、4、2是被_(pat)继续(3n+1)猜想
神雕侠侣2手游11月28日停服维护了什么,很多网友都遇到了这样的问题。这个问题该如何解决呢?下面小编就带来神雕侠侣2手游11月28日更新内容汇总,希望可以帮到你!亲爱的少侠为了给您带来更好的游戏体验,《神雕侠侣2》手游将于11月28日9:00-10:00进行例行停服维护,届时将无法登入游戏。若提前完成维护,我们将提前开服。请各位少侠提前做好准备,以免造成损失。维护结束后将统一奉上补偿,感谢您的支持...
Android 热修复 Tinker
一.常用属性举例:<select id="selectPerson" parameterType="int" resultType="hashmap"> SELECT * FROOM PRESON WHERE ID = #{id}</select>属性配置实例<select id="selectPerson" parame..._"
DDAlex 2019-03-05 14:37 原文链接:https://msd.misuland.com/pd/2884250137616454120原论文:Generating Adversarial Malware Examples for Black-Box Attacks Based on GAN引用论文:2001 Data Mining Methods ..._generating adversarial malware examples for black-box attacks based on gan引
大家好,我是山西农业大学软件学院来的码农。2013年9月到2016年6月在山西太谷上大学,2016年9月到帝都实训,2017年4月开始找工作。 在校期间我经历说丰富也算丰富,创业、社团、贴吧、学生会、兼职,什么都干了,没挂科,走自己的路,没事写写代码。但是遗憾也多,撇不到妹子,玩的不尽兴,学的有几下子,但是离大神还远的很。技能树点的有些歪,初中就点了数字媒体,大三突然走了java开发。还是审
**顶点计划**
转自https://blog.51cto.com/6930123/2115373一、为什么需要VLAN1.1、什么是VLAN?VLAN(Virtual LAN),翻译成中文是“虚拟局域网”。LAN可以是由少数几台家用计算机构成的网络,也可以是数以百计的计算机构成的企业网络。VLAN所指的LAN特指使用路由器分割的网络——也就是广播域。在此让我们先复习一下广播域的概念。广播域...
模块独立性模块独立性是指每个模块只完成系统要求的独立子功能,并且与其他模块的联系最少且接口最简单。衡量模块独立性的标准是耦合性和内聚性。(低耦合高内聚)耦合性耦合性也成为模块间联系,指软件系统结构中各模块间相互联系的紧密程度的一种度量。模块之间联系越紧密,其耦合性就越强,模块的独立性就越差。耦合性种类(低->高)无直接耦合、数据耦合、标记耦合、控制耦合、公共耦合、内容耦合无直接..._模块独立性
前言经常在群里听到大家对Android抱有一些消极的态度,说Android凉了,想要换个方向,但是如果换个方向就能变成大牛的话,那大家都换就好了。其实任何方向都存在”二八“定律,总有20%混的很好的人,我们要努力成为那20%,所以对自己的要求要逐渐提高,走出舒适区,尝试破局!现在已经不能停留在熟练使用RxJava,Retrofit,OkHttp以及各种图片库了,而是要源码级彻底掌握他们。要清楚,一个库再牛逼,那也是作者牛逼,所以我们要尽可能懂其中的原理。给大家几个建议哈,首先要耐得住寂寞,不要被外界