39 题: 什么是“大O”符号的简单英语解释?

在...创建的问题 Fri, Jul 22, 2016 12:00 AM

我更喜欢尽可能少的正式定义和简单的数学。

    
4766
  1. 摘要:算法复杂性的上限。另请参阅类似问题 Big O,您如何计算/近似?有一个很好的解释。
    2009-01-28 11:18:44Z
  2. 其他答案非常好,只需要了解一个细节:O(log n)或类似方法,它取决于“长度”或“大小”输入,而不是值本身。这可能很难理解,但非常重要。例如,当您的算法在每次迭代中将事物分成两部分时,会发生这种情况。
    2009-01-28 11:23:43Z
  3. 在麻省理工学院“计算机科学与编程导论”课程第8讲中,有一个专门讨论算法复杂性的讲座 youtube.com/watch?v=ewd7Lf2dr5Q 这不是完全简单的英语,但可以通过易于理解的示例给出很好的解释。
    2010-07-17 20:57:40Z
  4. 大O是对函数最坏情况性能的估计,假设算法将执行最大迭代次数。
    2012-08-28 00:16:57Z
  5. 2013-09-07 18:02:25Z
  6. 醇>
    30答案                              30 跨度>                         

    快速说明, Big O表示法(上限)几乎肯定会让人感到困惑与Theta符号(这是一个双方界限)。根据我的经验,这实际上是非学术环境中的典型讨论。对由此引起的任何混乱道歉。


    使用此图可以显示Big O复杂性:

    我可以为Big-O表示法提供的最简单的定义是:

    Big-O表示法是算法复杂性的相对表示。

    在这句话中有一些重要而刻意选择的词语:

      
    • 亲戚:你只能比较苹果和苹果。您无法将算法与算术乘法进行比较,而是对整数列表进行排序。但是比较两种算法进行算术运算(一次乘法,一次加法)会告诉你一些有意义的事情;
    •   
    • 表示: Big-O(最简单的形式)减少了算法与单个变量之间的比较。该变量基于观察或假设来选择。例如,通常基于比较操作来比较排序算法(比较两个节点以确定它们的相对排序)。这假设比较昂贵。但是,如果比较便宜但交换费用昂贵呢?它改变了比较;和
    •   
    • 复杂性:如果需要一秒钟来排序10,000个元素需要多长时间才能排序一百万个?在这种情况下,复杂性是对其他事物的相对衡量标准。
    •   

    当你读完其余内容后,回过头来重读上面的内容。

    我能想到的Big-O最好的例子就是做算术。取两个数字(123456和789012)。我们在学校学到的基本算术运算是:

      
    • 此外;
    •   
    • 减法;
    •   
    • 乘法;和
    •   
    • 分。
    •   

    这些都是操作或问题。一种方法o解决这些问题称为算法

    添加是最简单的。您将数字向上排列(向右)并在列中添加数字,在结果中写入该添加的最后一个数字。该数字的“十”部分将转移到下一栏。

    让我们假设这些数字的加法是该算法中最昂贵的操作。按理说,要将这两个数字加在一起,我们必须将6位数加在一起(并且可能带有7位数)。如果我们将两个100位数字加在一起,我们必须做100次加法。如果我们添加两个 10,000个数字,我们必须添加10,000个。

    看模式? 复杂度(作为操作数)与较大数字中的位数 n 成正比。我们称之为 O(n)线性复杂性

    减法类似(除非你需要借用而不是随身携带)。

    乘法是不同的。你将数字排成一行,取下面数字中的第一个数字,然后依次将它与顶部数字中的每个数字相乘,依此类推。因此,要将两个6位数相乘,我们必须进行36次乘法运算。我们可能需要进行多达10或11列添加以获得最终结果。

    如果我们有两个100位数字,我们需要进行10,000次乘法和200次加法。对于两百万个数字,我们需要做一万亿次(10次 12次)乘法和两百万次加法。

    当算法按n- 平方进行缩放时,这是 O(n 2 二次复杂度 。现在是介绍另一个重要概念的好时机:

    我们只关心复杂性中最重要的部分。

    精明的人可能已经意识到我们可以将操作次数表示为:n 2 + 2n。但正如你从我们的例子中看到的那样,每个数字为两位数百万,第二项(2n)变得无关紧要(占该阶段总运算的0.0002%)。

    人们可以注意到我们在这里假设了最糟糕的情况。如果其中一个是4位数而另一个是6位数,则乘以6位数字,那么我们只有24次乘法。我们仍然计算出'n'的最坏情况,即当两者都是6位数时。因此,Big-O表示法是关于算法的最坏情况

    电话簿

    我能想到的下一个最好的例子是电话簿,通常称为白页或类似的,但它会因国家而异。但我说的是那个按姓氏列出人名,然后是首字母或名字,可能是地址,然后是电话号码的人。

    现在,如果您指示计算机在包含1,000,000个名字的电话簿中查找“John Smith”的电话号码,您会怎么做?忽略这样一个事实,你可以猜到S开始了多远(让我们假设你不能),你会做什么?

    一个典型的实现可能是打开到中间,取500,000 th 并将其与“Smith”进行比较。如果恰好是“史密斯,约翰”,我们真的很幸运。更有可能的是,“约翰史密斯”将在该名称之前或之后。如果是在我们之后,我们将电话簿的后半部分分成两半并重复。如果是在那之前,我们将电话簿的前半部分分成两半并重复。等等。

    这称为二进制搜索,无论您是否意识到,它每天都会在编程中使用。

    因此,如果您想在一百万个名字的电话簿中找到一个名字,您最多可以通过这样做20次来找到任何名称。在比较搜索算法时,我们认为这种比较是我们的'n'。

      
    • 对于3个名字的电话簿,需要进行2次比较(最多)。
    •   
    • 7最多需要3个。
    •   
    • 15岁需要4个。
    •   
    • ...
    •   
    • 1,000,000需要20。
    •   

    这真是令人难以置信的好不是吗?

    在Big-O术语中,这是 O(log n)对数复杂度。现在所讨论的对数可以是ln(基数e),log 10 ,log 2 或其他一些基数。无论是O(log n)还是O(2n 2 ),O(100n 2 )仍然都是O(n 2 )。

    此时有必要解释Big O可用于通过算法确定三种情况:

      
    • 最佳案例:在电话簿搜索中,最好的情况是我们在一次比较中找到该名称。这是 O(1)常量复杂性;
    •   
    • 预期案例如上所述,这是O(log n);和
    •   
    • 最坏情况:这是也是O(log n)。
    •   

    通常我们不关心最好的情况。我们对预期和最坏的情况感兴趣。有时这些中的一个或另一个会更重要。

    回到电话簿。

    如果您有电话号码并希望找到姓名怎么办?警方有一本反向电话簿,但这些查询被公众拒绝。或者是他们?从技术上讲,您可以在普通电话簿中反向查找数字。怎么样?

    您从名字开始并比较数字。如果它是一场比赛,那么很棒,如果没有,你继续前进。你必须这样做,因为电话簿无序(无论如何都是电话号码)。

    所以要找到一个给出电话号码的名字(反向查询):

      
    • 最佳案例: O(1);
    •   
    • 预期案例 O(n)(500,000);和
    •   
    • 最坏情况: O(n)(1,000,000)。
    •   

    旅行推销员

    这是计算机科学中一个非常着名的问题,值得一提。在这个问题上你有N个城镇。这些城镇中的每一个都通过一定距离的道路与一个或多个其他城镇相连。旅行推销员的问题是找到访问每个城镇的最短旅行。

    听起来很简单?再想一想。

    如果你有3个城镇A,B和C,所有城市之间有道路,那么你可以去:

      
    • A→B→C
    •   
    • A→C→B
    •   
    • B→C→A
    •   
    • B→A→C
    •   
    • C→A→B
    •   
    • C→B→A
    •   

    实际上还不到那个,因为其中一些是等价的(例如,A→B→C和C→B→A是等价的,因为它们使用相同的道路,只是相反)。

    实际上有3种可能性。

      
    • 把它带到4个城镇,你有(iirc)12种可能性。
    •   
    • 5岁就是60岁。
    •   
    • 6变为360。
    •   

    这是一个称为 factorial 的数学运算的函数。基本上是:

      
    • 5! = 5×4×3×2×1 = 120
    •   
    • 6! = 6×5×4×3×2×1 = 720
    •   
    • 7! = 7×6×5×4×3×2×1 = 5040
    •   
    • ...
    •   
    • 25! = 25×24×...×2×1 = 15,511,210,043,330,985,984,000,000
    •   
    • ...
    •   
    • 50! = 50×49×...×2×1 = 3.04140932×10 64
    •   

    因此,旅行商问题的大O是 O(n!)阶乘或组合复杂性

    当你到达200个城镇时,宇宙中没有足够的时间来解决传统计算机的问题。

    要考虑的事情。

    多项式时间

    我想要快速提及的另一点是,任何具有 O(n a 复杂度的算法都被认为具有多项式复杂度或可在多项式时间中解决。

    O(n),O(n 2 )等都是多项式时间。有些问题在多项式时间内无法解决。因此,世界上使用了某些东西。公钥加密是一个很好的例子。在计算上很难找到两个非常大的素数因子。如果不是,我们就无法使用我们使用的公钥系统。

    无论如何,这是我(希望简单的英语)对Big O(修订版)的解释。

        
    6390
    2017-06-30 03:17:23Z
    1. 虽然其他答案侧重于解释O(1),O(n ^ 2)等人之间的差异....你的是详细说明如何算法的可以分为n ^ 2,nlog(n)等+1,这是一个很好的答案,帮助我理解Big O符号
      2009-01-28 11:42:39Z
    2. 可能想要添加big-O表示上限(由算法给出),big-Omega给出下限(通常作为证明独立于一个特定的算法)和big-Theta意味着已知到达该下界的“最优”算法。
      2009-02-02 19:16:22Z
    3. 如果您正在寻找最长的答案,这是好的,但不是以最简单的方式解释Big-O的答案。
      2010-07-16 18:21:59Z
    4. - 1:这是公然错误:_“BigOh算法的复杂度是相对的表示“.No。BigOh是一个渐近上界,很好地独立于计算机科学.O(n)是线性的。不,你把BigOh与theta混淆.log n是O(n)。 1是O(n)。这个答案(以及评论)的赞成数量,这使得将Theta与BigOh混淆的基本错误令人非常尴尬......
      2011-05-24 04:44:04Z
    5. “当你到达200个城镇时,宇宙中没有足够的时间来解决传统计算机的问题。”当宇宙即将结束时?
      2012-06-18 10:43:39Z
    6. 醇>

    它显示了算法如何扩展。

    O(n 2 :称为二次复杂度

    • 1项:1秒
    • 10项:100秒
    • 100项:10000秒

    请注意,项目数量增加了10倍,但时间增加了10倍 2 。基本上,n = 10,因此O(n 2 )给出了比例因子n 2 ,即10 2

    O(n):称为线性复杂性

    • 1项:1秒
    • 10项:10秒
    • 100项:100秒

    这次项目数量增加了10倍,时间也增加了10倍。 n = 10,所以O(n)的比例因子是10。

    O(1):称为常量复杂性

    • 1项:1秒
    • 10项:1秒
    • 100项:1秒

    项目数仍然增加10倍,但O(1)的比例因子始终为1.

    O(log n):称为对数复杂度

    • 1项:1秒
    • 10项:2秒
    • 100项:3秒
    • 1000项:4秒
    • 10000项:5秒

    计算次数仅增加输入值的对数。所以在这种情况下,假设每次计算需要1秒,输入n的日志就是所需的时间,因此为log n

    这就是它的要点。他们减少了数学,所以它可能不完全是n 2 或者它们所说的,但这将是缩放的主要因素。

        
    696
    2014-10-13 16:53:20Z
    1. 这个定义到底意味着什么? (项目数仍然增加10倍,但O(1)的比例因子始终为1.)
      2010-03-25 22:10:14Z
    2. 不是秒,操作。此外,你错过了阶乘和对数时间。
      2010-07-17 01:27:04Z
    3. 这并不能很好地解释O(n ^ 2)可能正在描述一个精确运行的算法.01 * n ^ 2 + 999999 * n + 999999重要的是要知道使用这种尺度比较算法,并且当n'足够大'时比较起作用。 Python的timsort实际上对小型数组使用插入排序(最差/平均情况O(n ^ 2)),因为它的开销很小。
      2012-05-21 23:14:36Z
    4. 这个答案也会混淆大O符号和Theta符号。对于所有输入(通常简写为1)返回1的n的函数实际上是O(n ^ 2)(即使它也在O(1)中)。类似地,仅需要执行花费恒定时间量的一个步骤的算法也被认为是O(1)算法,但也被认为是O(n)和O(n ^ 2)算法。但也许数学家和计算机科学家不同意这个定义: - /。
      2013-08-08 11:11:24Z
    5. O(log n)在这个答案中考虑的对数复杂度是基数10.一般来说,标准是用基数2来计算。应该记住这个事实不应该混淆。也正如@ChrisCharabaruk提到的那样复杂性表示操作数而不是秒数。
      2016-02-17 06:46:36Z
    6. 醇>

    Big-O表示法(也称为“渐近增长”表示法)是当您忽略原点附近的常数因子和东西时,“看起来像”的函数。我们用它来谈论如何缩放


    基本强>

    表示“足够”的大输入......

    •  f(x) ∈ O(upperbound)表示f“增长不快于”upperbound
    •  f(x) ∈ Ɵ(justlikethis)意味着f“增长完全像”justlikethis
    •  f(x) ∈ Ω(lowerbound)意味着f“增长不慢于”lowerbound

    big-O表示法并不关心常数因素:函数9x²被称为“完全像10x²”。 big-O 渐近符号也不关心非渐近的东西(“原点附近的东西”或“当问题大小很小时会发生什么”):函数10x²据说“长得很像”10x² - x + 2

    为什么要忽略等式中较小的部分?因为当你考虑越来越大的尺度时,它们会被等式的大部分完全相形见绌;他们的贡献变得相形见绌和无关紧要。 (参见示例部分。)

    换句话说,当你走向无限时,它就是比率如果你将实际时间除以O(...),你将得到一个大输入限制的常数因子。直观地说这是有道理的:如果你可以将一个乘以得到另一个。也就是说,当我们说...时,

     
    actualAlgorithmTime(N) ∈ O(bound(N))
                                           e.g. "time to mergesort N elements 
                                                 is O(N log(N))"
    

    ...这意味着 为“足够大”的问题大小N (如果我们忽略原点附近的东西),则存在一些常数(例如2.5,完全弥补):

     
    actualAlgorithmTime(N)                 e.g. "mergesort_duration(N)       "
    ────────────────────── < constant            ───────────────────── < 2.5 
           bound(N)                                    N log(N)         
    

    常数有很多种选择;通常,“最佳”选择被称为算法的“常数因子”...但我们经常忽略它,就像忽略非最大项一样(参见常数因子部分,为什么它们通常不重要)。你也可以把上面的等式想象成一个界限,说“在最坏的情况下,它所用的时间永远不会比大约N*log(N)差,在2.5倍之内(我们不关心的一个常数因素)很多)“。

    一般来说,O(...)是最有用的,因为我们经常关心最坏情况的行为。如果f(x)代表处理器或内存使用情况“坏”,那么“f(x) ∈ O(upperbound)”意味着“upperbound是处理器/内存使用情况最糟糕的情况”。


    应用强>

    作为纯粹的数学结构,big-O表示法不仅限于讨论处理时间和记忆。您可以使用它来讨论缩放有意义的任何事物的渐近性,例如:

    • 一方N人中可能发生的握手次数(Ɵ(N²),特别是N(N-1)/2,但重要的是它“像”一样“)
    • 概率预期将某些病毒式营销视为时间函数的人数
    • 网站延迟如何随CPU或GPU或计算机集群中的处理单元数量而变化
    • CPU上的热量输出如何随晶体管数量,电压等而变化
    • 算法需要运行多长时间,作为输入大小的函数
    • 算法需要运行多少空间,作为输入大小的函数

    示例强>

    对于上面的握手示例,一个房间里的每个人都会震动其他人的手。在那个例子中,#handshakes ∈ Ɵ(N²)。为什么呢?

    备份一下:握手的数量恰好是n-choose-2或N*(N-1)/2(每个N人都握着N-1其他人的手,但是这个双手握手所以除以2):

    然而,对于非常多的人来说,线性项N相形见绌并且有效地为该比率贡献了0(在图表中:随着参与者数量变大,对角线上空盒子的比例随总箱数变小)。因此,缩放行为为order N²,或握手数“增长为N²”。

     
    #handshakes(N)
    ────────────── ≈ 1/2
         N²
    

    就好像图表对角线上的空框(N *(N-1)/2复选标记)甚至不存在(N 2 复选标记渐近)。

    (来自“普通英语”的临时题词:)如果你想对自己证明这一点,你可以在比率上执行一些简单的代数,将它分成多个术语(lim表示“考虑在极限之内”,如果你还没有看到它就忽略它,它只是表示法因为“和N真的很大”):

     
        N²/2 - N/2         (N²)/2   N/2         1/2
    lim ────────── = lim ( ────── - ─── ) = lim ─── = 1/2
    N→∞     N²       N→∞     N²     N²      N→∞  1
                                   ┕━━━┙
                 this is 0 in the limit of N→∞:
                 graph it, or plug in a really large number for N
    

    tl; dr:对于大值,握手'看起来像'x²那么多,如果我们要记下#handshakes /x²的比例,那么我们不需要完全x²握手甚至不会在十进制中显示任意大的时间。

      

    e.g。对于x = 1百万,比例#handshakes /x²:0.499999 ...


    建立直觉

    这让我们可以发表像......

    这样的陈述
      

    “对于足够大的inputize = N,无论常数因素是什么,如果我 double 输入大小......

    • ...我将O(N)(“线性时间”)算法的时间加倍。“
        

      N →(2N)= 2( N

    • ...我将O(N²)(“二次时间”)算法的时间加倍(四倍)。“(例如,问题100x大到100²= 10000x那么长...可能不可持续)
        

      →(2N)²= 4(

    • ...我是O(N³)(“立方时间”)算法所需的时间的两倍(八倍)。“(例如,问题100倍大,需要100³= 1000000x那么长...非常不可持续)
        

      cN³→c(2N)³= 8(cN³

    • ...我在O(log(N))(“对数时间”)算法的时间内添加固定数量。“(便宜!)
        

      c log(N)→c log(2N)=(c log(2))+( c log(N))=(固定金额)+ ( c log(N)

    • ...我没有改变O(1)(“恒定时间”)算法所花费的时间。“(最便宜!)
        

      c * 1 c * 1

    • ......我“(基本上)加倍”O(N log(N))算法所需的时间。“(相当常见)
        

      它小于O(N 1.000001 ),您可能愿意基本上称之为线性

    • ......我荒谬地增加了O(2 N )(“指数时间”)算法的时间。“(你要加倍(或三倍等)时间只是通过一个单位增加问题)
        

      2 N →2 2N =(4 N )......... ......换句话说...... 2 N →2 N + 1 = 2 N 2 1 = 2 2 N

    [对于数学上的倾向,你可以将鼠标悬停在剧透小说上以获得次要的注释]

    (归功于 https://stackoverflow.com/a/487292/711085

    (从技术上讲,常数因素可能在一些更深奥的例子中很重要,但我已经在上面提到了一些事情(例如在log(N)中),这样就没有了。

    这些是程序员和应用计算机科学家用作参考点的增长顺序。他们一直看到这些。 (因此,虽然你在技术上可以认为“加倍输入会使O(√N)算法慢1.414倍”,但最好将其视为“这比对数更差但比线性更好”。)


    常数因素

    通常我们不关心具体的常数因素是什么,因为它们不会影响函数的增长方式。例如,两个算法可能都需要O(N)个时间才能完成,但其中一个可能是另一个算法的两倍。除非因素非常大,否则我们通常不会太在意,因为优化是一项棘手的工作(何时优化早产?);仅选择具有更好的大O的算法的行为通常会提高数量级的性能。

    一些渐近优越的算法(例如,非比较O(N log(log(N)))种类)可以具有如此大的常数因子(例如100000*N log(log(N))),或者相对较大的开销,如O(N log(log(N))),隐藏+ 100*N,即使在“大数据“。


    为什么O(N)有时是你能做的最好的,也就是为什么我们需要数据结构

    如果您需要读取所有数据,O(N)算法在某种意义上是“最佳”算法。 读取一堆数据的行为是O(N)操作。将其加载到内存中通常为O(N)(如果您有硬件支持,或者根本没有时间,则更快如果你已经阅读了数据)。但是,如果您触摸甚至每个数据(或者甚至是其他所有数据),您的算法将花费O(N)时间来执行此操作。不管你的实际算法需要多长时间,它至少是O(N),因为它花了那么多时间查看所有数据。

    写作行为也是如此。打印N个事物的所有算法将花费N次,因为输出至少那么长(例如打印出所有排列(重新排列的方式)一组N个扑克牌是阶乘的:O(N!))。

    这促使了数据结构的使用:数据结构只需要读取一次数据(通常是O(N)次),加上一些任意数量的预处理(例如O(N)O(N log(N))O(N²))我们尝试保持小。此后,修改数据结构(插入/删除/等)并对数据进行查询只需要很少的时间,例如O(1)O(log(N))。然后,您继续进行大量查询!一般来说,你愿意提前做的工作越多,你以后做的工作就越少。

    例如,假设您拥有数百万条道路段的纬度和经度坐标,并希望找到所有街道交叉路口。

    • 朴素的方法:如果你有一个街道交叉口的坐标,并想要检查附近的街道,你每次都要经历数百万个段,并检查每个段是否相邻。
    • 如果你只需要这样做一次,那么只用一次O(N)的天真方法就不会有问题,但如果你想做多次(在这种情况下,N次,一次用于每个部分),我们必须做O(N²)工作,或1000000²= 1000000000000操作。不好(现代计算机每秒可以执行大约10亿次操作)。
    • 如果我们使用称为哈希表的简单结构(即时速度查找表,也称为哈希表或字典),我们通过在O(N)时间内预处理所有内容来支付少量费用。此后,平均只需要通过其键查找一些东西(在这种情况下,我们的关键是纬度和经度坐标,四舍五入到网格;我们搜索相邻的网格空间,其中只有9,这是一个常数)。
    • 我们的任务从一个不可行的O(N²)变成了一个可管理的O(N),我们所要做的只是支付一笔不小的费用来制作哈希表。
    • 类比:在这种特殊情况下的类比是一个拼图游戏:我们创建了一个利用数据属性的数据结构。如果我们的路段就像拼图一样,我们会根据颜色和图案进行分组。然后我们利用它来避免以后做额外的工作(比较相似颜色的拼图,而不是每个其他单个拼图)。

    故事的寓意:数据结构让我们加快了运营速度。更高级的数据结构可以让您以非常聪明的方式组合,延迟甚至忽略操作。不同的问题会有不同的类比,但它们都涉及以一种利用我们关心的某种结构的方式组织数据,或者我们人为地将其用于簿记。我们提前工作(基本上是计划和组织),现在重复的任务要容易得多!


    实际示例:在编码时可视化增长顺序

    渐近符号的核心是与编程完全分开。渐近符号是用于思考事物如何缩放的数学框架,并且可以用于许多不同的领域。那就是说......这就是你应用渐近符号进行编码的方式。

    基础知识:每当我们与大小为A的集合中的每个元素(例如数组,集合,地图的所有键等)进行交互,或执行循环的迭代时,这是一个多重因子大小A.为什么我说“乘法因子”? - 因为循环和函数(几乎按定义)具有乘法运行时间:迭代次数,循环中完成的工作次数(或函数:次数)你调用函数,在函数中完成的工作次数)。 (如果我们不做任何花哨的事情,例如跳过循环或提前退出循环,或者基于参数更改函数中的控制流,这是很常见的。这是一些可视化技术的示例,附带伪代码。

    (这里,x代表恒定时间工作单位,处理器指令,解释器操作码,等等)

     
    for(i=0; i<A; i++)        // A * ...
        some O(1) operation     // 1
    
    --> A*1 --> O(A) time
    
    visualization:
    
    |<------ A ------->|
    1 2 3 4 5 x x ... x
    
    other languages, multiplying orders of growth:
      javascript, O(A) time and space
        someListOfSizeA.map((x,i) => [x,i])               
      python, O(rows*cols) time and space
        [[r*c for c in range(cols)] for r in range(rows)]
    

    示例2:

     
    for every x in listOfSizeA:   // A * (...
        some O(1) operation         // 1
        some O(B) operation         // B
        for every y in listOfSizeC: // C * (...
            some O(1) operation       // 1))
    
    --> O(A*(1 + B + C))
        O(A*(B+C))        (1 is dwarfed)
    
    visualization:
    
    |<------ A ------->|
    1 x x x x x x ... x
    
    2 x x x x x x ... x ^
    3 x x x x x x ... x |
    4 x x x x x x ... x |
    5 x x x x x x ... x B  <-- A*B
    x x x x x x x ... x |
    ................... |
    x x x x x x x ... x v
    
    x x x x x x x ... x ^
    x x x x x x x ... x |
    x x x x x x x ... x |
    x x x x x x x ... x C  <-- A*C
    x x x x x x x ... x |
    ................... |
    x x x x x x x ... x v
    

    示例3:

     
    function nSquaredFunction(n) {
        total = 0
        for i in 1..n:        // N *
            for j in 1..n:      // N *
                total += i*k      // 1
        return total
    }
    // O(n^2)
    
    function nCubedFunction(a) {
        for i in 1..n:                // A *
            print(nSquaredFunction(a))  // A^2
    }
    // O(a^3)
    

    如果我们做了一些稍微复杂的事情,你仍然可以直观地想象发生了什么:

     
    for x in range(A):
        for y in range(1..x):
            simpleOperation(x*y)
    
    x x x x x x x x x x |
    x x x x x x x x x   |
    x x x x x x x x     |
    x x x x x x x       |
    x x x x x x         |
    x x x x x           |
    x x x x             |
    x x x               |
    x x                 |
    x___________________|
    

    在这里,您可以绘制的最小可识别轮廓是重要的;三角形是二维形状(0.5 A ^ 2),就像一个正方形是二维形状(A ^ 2);两个常数因子保持在两者之间的渐近比例,但是我们忽略它就像所有因素一样......(这种技术有一些不幸的细微差别我不会在这里进行;它可能会误导你。)

    当然这并不意味着循环和功能都很糟糕;相反,它们是现代编程语言的基石,我们喜欢它们。但是,我们可以看到,我们将循环,函数和条件与我们的数据(控制流等)一起编织的方式模仿了我们程序的时间和空间使用!如果时间和空间的使用成为一个问题,那就是我们诉诸于聪明,并找到一个我们没有考虑的简单算法或数据结构,以某种方式减少增长的顺序。尽管如此,这些可视化技术(虽然它们并不总是有效)可以让您在最坏情况下运行时进行初步猜测。

    我们可以直观地识别出另一件事:

     
    <----------------------------- N ----------------------------->
    x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x
    x x x x x x x x x x x x x x x x
    x x x x x x x x
    x x x x
    x x
    x
    

    我们可以重新排列这个并看到它是O(N):

     
    <----------------------------- N ----------------------------->
    x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x
    x x x x x x x x x x x x x x x x|x x x x x x x x|x x x x|x x|x
    

    或者你可以对数据进行log(N)次传递,对于O(N * log(N))总时间:

     
       <----------------------------- N ----------------------------->
     ^  x x x x x x x x x x x x x x x x|x x x x x x x x x x x x x x x x
     |  x x x x x x x x|x x x x x x x x|x x x x x x x x|x x x x x x x x
    lgN x x x x|x x x x|x x x x|x x x x|x x x x|x x x x|x x x x|x x x x
     |  x x|x x|x x|x x|x x|x x|x x|x x|x x|x x|x x|x x|x x|x x|x x|x x
     v  x|x|x|x|x|x|x|x|x|x|x|x|x|x|x|x|x|x|x|x|x|x|x|x|x|x|x|x|x|x|x|x
    

    无关但值得一提:如果我们执行散列(例如字典/散列表查找),那就是O(1)的因子。那很快。

     
    [myDictionary.has(x) for x in listOfSizeA]
     \----- O(1) ------/    
    
    --> A*1 --> O(A)
    

    如果我们做一些非常复杂的事情,例如使用递归函数或分而治之算法,你可以使用主定理(通常是有效的),或者在荒谬的情况下,Akra-Bazzi定理(几乎总是有效)你在维基百科上查找算法的运行时间。

    但是,程序员并不这么认为,因为最终,算法直觉才成为第二天性。你将开始编写一些效率低下的东西,并立即想到“我在做什么非常低效?”。如果答案是肯定的并且您预见它实际上很重要,那么您可以退一步思考各种技巧以使事情运行得更快(答案几乎总是“使用哈希表”,很少“使用树”,很少有点复杂的事情。)


    摊销和平均案例复杂度

    还有“摊销”和/或“平均案例”的概念(注意这些是不同的)。

    平均情况:这只不过是使用big-O表示法来表示函数的期望值,而不是函数本身。在通常情况下,您认为所有输入都具有相同的可能性,平均情况只是运行时间的平均值。例如,对于快速排序,即使最糟糕的情况是O(N^2)对于一些非常糟糕的输入,平均情况通常是O(N log(N))(真正糟糕的输入数量非常少,所以很少我们在一般情况下没有注意到它们)。

    分摊最坏情况:某些数据结构可能具有较大的最坏情况复杂性,但保证如果您执行其中许多操作,您执行的平均工作量将更好比最糟糕的情况。例如,您可能拥有通常需要O(1)时间的数据结构。然而,偶尔它会'打嗝'并且需要O(N)时间进行一次随机操作,因为它可能需要做一些记账或垃圾收集等等......但它承诺,如果它打嗝,它不会再次打嗝N更多操作。每次操作的最坏情况成本仍然是O(N),但是多次运行的摊销成本是每次操作O(N)/N = O(1)。由于大型操作非常罕见,因此可以考虑将大量的临时工作与其余工作融为一体。我们说这项工作是在大量的电话中“摊销”的,它渐渐消失了。

      

    摊销分析的类比:

         

    你开车。偶尔,你需要花10分钟去   加油站,然后花1分钟给油箱加气。   如果你每次去汽车的任何地方都这样做(花10美元   分钟开车到加油站,花几秒钟填满了   加仑的一小部分),这将是非常低效的。但如果你填补   每隔几天上升一次坦克,11分钟就开车去了   加油站在足够多的旅程中“摊销”,   你可以忽略它并假装你的所有行程都可能长5%。

    平均案例和摊销最坏情况之间的比较:

    • 平均情况:我们对输入做出一些假设;即如果我们的输入具有不同的概率,那么我们的输出/运行时将具有不同的概率(我们取平均值)。通常我们假设我们的输入都是同等可能的(均匀概率),但如果真实世界输入d如果不符合我们对“平均输入”的假设,平均输出/运行时计算可能毫无意义。如果你预期一致的随机输入,那么考虑一下这很有用!
    • 摊销的最坏情况:如果你使用摊销的最坏情况数据结构,那么性能将保证在最终的最终情况下......最终(即使输入是由一个知道所有事情的邪恶恶魔选择的试图搞砸你)。通常我们使用它来分析算法,这些算法在性能上可能非常“不连贯”,出现意外的大型打嗝,但随着时间的推移,其性能与其他算法一样好。 (但是,除非你的数据结构有许多优秀工作的上​​限,否则它是否愿意拖延,一个邪恶的攻击者可能会迫使你一次性赶上最大量的拖延工作。

    但是,如果你是合理地担心关于攻击者,除了摊销和平均情况外,还有许多其他算法攻击媒介需要担心。)

    平均案例和摊销都是非常有用的工具,可以在考虑扩展时进行思考和设计。

    (如果对此子主题感兴趣,请参阅平均案例和摊销分析之间的差异。)


    多维大O

    大多数时候,人们都没有意识到工作中有多个变量。例如,在字符串搜索算法中,您的算法可能需要时间O([length of text] + [length of query]),即它在两个变量(如O(N+M))中是线性的。其他更天真的算法可能是O([length of text]*[length of query])O(N*M)。忽略多个变量是我在算法分析中看到的最常见的疏忽之一,在设计算法时可能会让您失望。


    整个故事

    请记住,大O不是整个故事。您可以通过使用缓存来大幅加速某些算法,使其无法缓存,通过使用RAM而不是磁盘来避免瓶颈,使用并行化或提前完成工作 - 这些技术通常是独立的虽然您经常会看到并行算法的大O符号中的核心数量。

    另请注意,由于程序的隐藏限制,您可能并不真正关心渐近行为。您可能正在使用有限数量的值,例如:

    • 如果您要对5个元素进行排序,则不想使用快速的O(N log(N))快速排序;你想使用插入排序,这恰好在小输入上表现良好。这些情况通常出现在分而治之的算法中,您可以将问题分解为越来越小的子问题,例如递归排序,快速傅里叶变换或矩阵乘法。
    • 如果某些值由于一些隐藏的事实而被有效限制(例如,平均人名在40个字母处受到轻微限制,并且人类年龄在150左右受到轻微限制)。您还可以在输入上强加边界以有效地使术语保持不变。

    实际上,即使在具有相同或相似渐近性能的算法中,它们的相对优点实际上也可能由其他因素驱动,例如:其他性能因素(quicksort和mergesort都是O(N log(N)),但quicksort利用了CPU缓存) );非性能考虑因素,如易于实施;图书馆是否可用,图书馆的信誉和维护程度如何。

    在500MHz计算机和2GHz计算机上,程序运行速度也会变慢。我们并不认为这是资源边界的一部分,因为我们考虑了机器资源(例如每个时钟周期)的缩放,而不是实际的秒。但是,有类似的东西可以“秘密”影响性能,例如您是否在仿真下运行,或者编译器是否优化了代码。这些可能会使一些基本操作花费更长时间(甚至相对于彼此),甚至可以渐进地加速或减慢某些操作(甚至相对于彼此)。在不同的实现和/或环境之间效果可能很小或很大。你是否需要切换语言或机器才能完成额外的工作?这取决于其他一百个原因(必要性,技能,同事,程序员生产力,时间的货币价值,熟悉程度,变通方法,为什么不装配或GPU等等),这可能比性能更重要。

    上述问题,如编程语言,几乎从未被视为常数因素的一部分(也不应该是);但是人们应该意识到它们,因为有时(尽管很少)它们可能会影响事物。例如在cpy中然而,本机优先级队列实现是渐近非最优的(O(log(N))而不是O(1),用于选择插入或find-min);你使用其他实现吗?可能不是,因为C实现可能更快,并且其他地方可能存在其他类似问题。有权衡;有时他们很重要,有时他们没有。


    编辑:“普通英语”解释在这里结束。)

    数学附录

    为了完整性,big-O表示法的精确定义如下:f(x) ∈ O(g(x))表示“f渐近上限为const * g”:忽略x的某些有限值以下的所有内容,存在一个常数这样|f(x)| ≤ const * |g(x)|。 (其他符号如下:就像O表示≤,Ω表示≥。有小写变体:o表示&lt;,ω表示&gt ;.)f(x) ∈ Ɵ(g(x))表示f(x) ∈ O(g(x))f(x) ∈ Ω(g(x))(上限和下限以g为单位) ):存在一些常数,使得f将始终位于const1*g(x)const2*g(x)之间的“波段”中。这是你可以做出的最强的渐近陈述,大致相当于==。 (对不起,为了清楚起见,我选择延迟提到绝对值符号,特别是因为我从未在计算机科学背景下看到过负面的值。)

    人们经常使用= O(...),这可能是更正确的'comp-sci'符号,并且完全合法使用; “f = O(...)”被读为“f是顺序... /f是xxx-以...为界”并且被认为是“f是渐近线是......的某种表达式”。我被教导使用更严格的∈ O(...)表示“是一个元素”(仍然像以前一样阅读)。 O(N²)实际上是一个等价类,也就是说,它是一组我们认为是相同的东西。在这种特殊情况下,O(N²)包含{2 N²,3 N²,1/2 N²,2 N² + log(N),- N² + N^1.9 ......等元素,并且无限大,但它仍然是一个集合。 =符号可能更常见,甚至被世界知名计算机科学家用于论文。此外,通常情况下,在休闲环境中,人们会说O(...),而他们的意思是Ɵ(...);这在技术上是正确的,因为事物Ɵ(exactlyThis)O(noGreaterThanThis)的子集......并且它更容易输入。 ; - )

        
    381
    2018-11-14 08:13:05Z
    1. 一个优秀的数学答案,但OP要求一个简单的英语答案。这种水平的数学描述不是理解答案所必需的,尽管对于特别注重数学的人来说,理解它可能比“普通英语”简单得多。然而OP要求后者。
      2013-07-02 22:19:52Z
    2. 推测OP以外的人可能会对这个问题的答案感兴趣。这不是网站的指导原则吗?
      2014-02-03 18:34:33Z
    3. 虽然我可以看到为什么人们可以略过我的答案并认为它太蹩脚(特别是“数学是新的普通英语”讽刺言论,自从删除后),原始问题询问关于函数的big-O,所以我试图明确地以一种补充普通英语直觉的方式讨论函数。这里的数学经常可以被掩盖,或者用高中数学背景来理解。我觉得人们可能会在最后看到数学附录,并假设这是答案的一部分,当它只是在那里看看真实的数学看起来是什么样。
      2015-04-03 04:39:54Z
    4. 这是一个很棒的答案;比投票最多的IMO要好得多。所需的“数学”不会超出理解“O”后括号中的表达式所需要的,没有使用任何例子的合理解释可以避免。
      2016-04-27 15:52:07Z
    5. “f(x)∈O(上限)意味着f”增长不快于“上限”这三个简单的措辞,但在数学上正确解释大哦,Theta,和欧米茄是金色的。他用简单的英语向我描述了在没有编写复杂的数学表达式的情况下,5个不同的来源似乎无法转化为我。谢啦! :)
      2016-09-04 22:20:10Z
    6. 醇>

    编辑:快速说明,这几乎肯定会让人感到困惑的是 Big O表示法(这是一个上层用Theta表示法(这是一个上限和下限)。根据我的经验,这实际上是非学术环境中的典型讨论。对由此引起的任何混乱道歉。

    用一句话说:随着工作规模的增加,完成工作需要多长时间?

    显然,只使用“size”作为输入,“time time”作为输出 - 如果你想谈论内存使用等,同样的想法也适用。

    这是一个我们想要干燥的N T恤的例子。我们假设让它们处于干燥位置非常快(即人类的相互作用可以忽略不计)。现实情况并非如此,当然......

    • 在外面使用清洗线:假设您有一个无限大的后院,洗涤在O(1)时间内干燥。无论你有多少,它都会得到相同的阳光和新鲜空气,所以尺寸不会影响干燥时间。

    • 使用滚筒式烘干机:每次装入10件衬衫,然后一小时后完成。 (忽略这里的实际数字 - 它们无关紧要。)因此,干燥50件衬衫需要干燥10件衬衫的次数。

    • 把所有东西都放在一个通风橱里:如果我们把所有东西放在一个大堆里,只要让一般温暖,那么中间衬衫要干燥需要很长时间。我不想猜测细节,但我怀疑这至少是O(N ^ 2) - 随着你增加洗涤负荷,干燥时间增加得更快。

    “大O”符号的一个重要方面是它说哪个算法对于给定的大小会更快。获取哈希表(字符串键,整数值)与对数组(字符串,整数)。基于字符串,在哈希表或数组中的元素中查找键是否更快? (即对于数组,“找到字符串部分与给定键匹配的第一个元素。”)哈希表通常是摊销的(〜=“平均”)O(1) - 一旦它们被设置,它应该采取同时在100条目表中查找条目,如1,000,000条目表中所示。在数组中查找元素(基于内容而不是索引)是线性的,即O(N) - 平均而言,您将不得不查看一半的条目。

    这是否使哈希表比查找数组更快?不必要。如果你有一个非常小的条目集合,一个数组可能会更快 - 你可以在计算你正在查看的哈希码的时间内检查所有字符串。然而,随着数据集变大,哈希表最终会击败数组。

        
    241
    2011-11-08 06:15:21Z
    1. 哈希表需要运行算法来计算实际数组的索引(取决于实现)。数组只有O(1),因为它只是一个地址。但这与这个问题无关,只是一个观察:)
      2009-01-28 11:29:54Z
    2. jon的解释与我想的问题有很多共同点。这正是一个人可以向某个妈妈解释它的方式,她最终会理解它我认为:)我喜欢衣服的例子(特别是最后一个,它解释了复杂性的指数增长)
      2009-01-28 11:32:26Z
    3. Filip:我不是在谈论通过索引来解决数组,我在谈论在数组中查找匹配的条目。你能重新阅读答案,看看是否仍然不清楚?
      2009-01-28 11:35:58Z
    4. @ Filip Ekberg我想你正在考虑一个直接地址表,其中每个索引直接映射到一个键,因此是O(1),但我相信Jon是谈论一组未分类的键/值对,你必须线性搜索。
      2011-07-29 09:41:13Z
    5. @ RBT:不,它不是二进制查找。它可以到达e立即哈希,仅基于从哈希码到桶索引的转换。之后,在存储桶中找到正确的哈希码可能是线性的,也可能是二进制搜索...但到那时你只占字典总大小的一小部分。
      2016-11-17 07:57:40Z
    6. 醇>

    Big O描述了函数增长行为的上限,例如当输入变大时函数的运行时。

    示例:

    • O(n):如果我将输入大小加倍,则运行时间加倍

    • O(n 2 ):如果输入大小是运行时四倍的两倍

    • O(log n):如果输入大小加倍,则运行时间增加一个

    • O(2 n ):如果输入大小增加1,则运行时间加倍

    输入大小通常是表示输入所需的位数。

        
    123
    2014-01-11 11:11:19Z
    1. 不正确!例如O(n):如果我将输入大小加倍,则运行时将乘以有限非零常数。我的意思是O(n)= O(n + n)
      2010-05-16 11:33:33Z
    2. 我在谈论f(n)= O(g(n))中的f,而不是你似乎理解的g。
      2010-08-06 12:30:15Z
    3. 我投了赞成票,但最后一句话对我的贡献不大。在讨论或测量Big(O)时,我们不经常谈论“位”。
      2011-09-05 16:41:08Z
    4. 你应该为O(n log n)添加一个例子。
      2011-09-22 15:50:33Z
    5. 这不是那么清楚,基本上它的表现比O(n)差一点。因此,如果n加倍,则运行时间乘以稍大于2的因子。
      2011-09-23 06:44:50Z
    6. 醇>

    程序员最常使用Big O表示法作为计算(算法)完成所需时间的近似度量,表示为输入集大小的函数。

    Big O可用于比较两种算法随着输入数量的增加而扩展的程度。

    更准确地说, Big O表示法用于表示函数的渐近行为。这意味着函数在接近无穷大时的行为方式。

    在许多情况下,算法的“O”将属于下列情况之一:

    • O(1) - 无论输入集的大小如何,完成时间都相同。一个例子是通过索引访问数组元素。
    • O(Log N) - 完成时间大致与log2(n)一致。例如,1024个项目大约需要32个项目的两倍,因为Log2(1024)= 10而Log2(32)= 5.例如,在二叉搜索树(BST)。
    • O(N) - 完成时间与输入集的大小成线性比例。换句话说,如果您将输入集中的项目数加倍,则算法大约需要两倍的时间。一个例子是计算链表中的项目数。
    • O(N Log N) - 完成时间增加了Log2(N)的结果乘以项目数。一个例子是堆排序快速排序
    • O(N ^ 2) - 完成时间大致等于项目数的平方。一个例子是冒泡排序
    • O(N!) - 完成时间是输入的阶乘组。一个例子是旅行商问题暴力解决方案

    当输入大小朝向无穷大增加时,大O忽略了对函数的增长曲线没有有意义贡献的因素。这意味着简单地忽略了添加到函数或乘以函数的常量。

        
    102
    2011-09-13 03:08:33Z
    1. cdiggins,如果我有O(N /2)复杂度,应该是O(N)还是O(N /2),例如复杂性如何我将循环一半的字符串。
      2017-05-12 15:08:29Z
    2. @ Melad这是一个常数(0.5)与函数相乘的例子。这被忽略,因为它被认为对非常大的N值有效。
      2017-05-18 19:47:55Z
    3. 醇>

    Big O只是一种以一种常见方式“表达”自己的方式,“运行我的代码需要多长时间/空间?”。

    你可能经常看到O(n),O(n 2 ),O(nlogn)等等,所有这些只是展示的方式;算法如何改变?

    O(n)意味着大O是n,现在你可能会想,“什么是n!?” “n”是元素的数量。想要在阵列中搜索项目的图像。您必须查看每个元素并将其视为“您是正确的元素/项目吗?”在最坏的情况下,该项目位于最后一个索引,这意味着它花费的时间与列表中的项目一样多,因此为了通用,我们说“哦,嘿,n是一个公平的给定数量的值!”

    那么你可能会理解“n 2 ”意味着什么,但更具体地说,你可以想到你有一个简单,最简单的排序算法;冒泡。该算法需要查看每个项目的整个列表。

    我的清单

    1. 1
    2. 6
    3. 3
    4. 醇>

      这里的流程将是:

    • 比较1和6,哪个最大? Ok 6处于正确的位置,向前移动!
    • 比较6和3,哦,3更少!让我们移动一下,好的清单改变了,我们需要从现在开始!

    这是O n 2 因为,您需要查看列表中的所有项目都有“n”项。对于每个项目,您再次查看所有项目,为了进行比较,这也是“n”,因此对于每个项目,您看起来都是“n”次,意味着n * n = n 2

    我希望这就像你想要的一样简单。

    但请记住,Big O只是一种以时间和空间的方式超越自我的方式。

        
    79
    2014-10-19 20:47:19Z
    1. 对于logN,我们考虑从0到N /2的循环运行O(log log N)?我的意思是程序是怎么样的?请原谅我纯粹的数学技能
      2015-09-30 10:52:49Z
    2. 醇>

    Big O描述了算法的基本缩放特性。

    Big O没有告诉你有关给定算法的大量信息。它切入骨骼并仅提供有关算法的缩放特性的信息,特别是算法的资源使用(思考时间或内存)如何根据“输入大小”进行缩放。

    考虑蒸汽机和火箭之间的区别。它们不仅仅是同一种物品的不同品种(例如,普锐斯发动机与兰博基尼发动机),但它们的核心是不同类型的推进系统。蒸汽机可能比玩具火箭更快,但没有蒸汽活塞发动机能够达到轨道运载火箭的速度。这是因为这些系统在达到给定速度(“输入尺寸”)所需的燃料关系(“资源使用”)方面具有不同的缩放特性。

    为什么这么重要?因为软件处理的问题可能因数据大小不同而有所不同。考虑一下。前往月球所需的速度与人类行走速度之间的比率小于10,000:1,与软件可能面临的输入尺寸范围相比,这是非常小的。而且由于软件可能面临输入大小的天文范围,因此算法的Big O复杂性可能会超越任何实现细节,这是基本的扩展性质。

    考虑规范排序示例。冒泡排序为O(n 2 ),而merge-sort为O(n log n)。假设您有两个排序应用程序,即使用冒泡排序的应用程序A和使用合并排序的应用程序B,并且假设对于大约30个元素的输入大小,应用程序A在排序时比应用程序B快1,000倍。如果您不必排序超过30个元素,那么您应该更喜欢应用程序A,因为它在这些输入大小上要快得多。但是,如果您发现可能需要对一千万个项目进行排序,那么您所期望的是,在这种情况下,应用程序B实际上最终比应用程序A快数千倍,这完全取决于每种算法的扩展方式。

        
    53
    2014-10-19 20:48:18Z

    这是我在解释Big-O的常见变种时倾向于使用的普通英语动物

    在所有情况下,首选列表中较高的算法列表中较低的算法。但是,迁移到更昂贵的复杂性类别的成本差异很大。

    O(1):强>

    没有增长。无论问题有多大,您都可以在相同的时间内解决问题。这有点类似于广播,无论广播范围内的人数是多少,广播都需要相同的能量才能在给定距离内广播。

    O(log n ):

    这种复杂性与 O(1)相同,只是它稍微差一点。出于所有实际目的,您可以将其视为非常大的常量缩放。处理1千到10亿件物品之间的工作差异只有6倍。

    O(名词的):强>

    解决问题的成本与问题的大小成正比。如果您的问题规模增加一倍,那么解决方案的成本会翻倍。由于大多数问题必须以某种方式扫描到计算机中,如数据录入,磁盘读取或网络流量,这通常是一个负担得起的缩放因子。

    O( n log n ):

    此复杂性与 O( n 非常相似。出于所有实际目的,这两者是等价的。这种复杂程度通常仍被认为是可扩展的。通过调整假设,一些 O( n log n 算法可以转换为 O( n 算法。例如,限制键的大小会减少从 O( n log n O( n )强>

    O(名词 2 ):强>

    生长为正方形,其中 n 是正方形边长。这与“网络效应”的增长率相同,网络中的每个人都可能知道网络中的其他人。增长是昂贵的。大多数可扩展的解决方案不能使用具有这种复杂程度的算法,而无需进行重要的体操。这通常适用于所有其他多项式复杂度 - O( n k - 以及。

    O(2 名词 ):强>

    不缩放。你没有希望解决任何非平凡的问题。用于了解要避免的内容,以及专家找到 O( n k 中的近似算法。

        
    38
    2014-03-10 06:51:52Z
    1. 你能否考虑一下O(1)的另一个类比?我的工程师想要讨论由于障碍物造成的射频阻抗。
      2016-03-10 23:02:28Z
    2. 我确实使用了“有点”这个词。
      2017-04-14 17:12:35Z
    3. 醇>

    Big O衡量算法使用的时间/空间相对于其输入的大小。

    如果算法为O(n),则时间/空间将以与输入相同的速率增加。

    如果算法为O(n 2 ),则时间/空间以其输入平方的速率增加。

    等等。

        
    35
    2014-10-19 20:49:11Z
    1. 这不是关于空间的。这是关于复杂性,这意味着时间。
      2009-01-28 11:35:02Z
    2. 我一直认为它可以是时间或空间。但不是同时两个。
      2009-01-28 12:58:59Z
    3. 复杂性绝对可以是空间。请看一下: en.wikipedia.org/wiki/PSPACE
      2010-08-08 15:58:49Z
    4. 这个答案是这里最“简单”的答案。以前的人实际上假设读者已经足够了解他们,但作家并不知道。他们认为他们很简单,但绝对不是。用漂亮的格式编写大量文本并制作难以为非CS人员制作的花哨的人工例子并不简单明了,对于大多数CS人来说非常有吸引力。用简单的英语解释CS术语根本不需要代码和数学。这个答案的+1虽然还不够好。
      2013-05-29 12:36:01Z
    5. 这个答案会产生(常见)错误,假设f = O(g)表示f和g是成比例的。
      2015-04-03 04:38:41Z
    6. 醇>

    测量软件程序的速度非常困难,当我们尝试时,答案可能非常复杂,并且充满异常和特殊情况。这是一个大问题,因为当我们想要将两个不同的程序相互比较以找出哪个是“最快的”时,所有这些异常和特殊情况都会分散注意力并且无益。

    由于所有这些无用的复杂性,人们试图用尽可能最小和最不复杂(数学)的表达来描述软件程序的速度。这些表达式是非常粗略的近似值:虽然运气不错,但它们将捕捉到软件是快还是慢的“本质”。

    因为它们是近似值,所以我们在表达式中使用字母“O”(Big Oh),作为一种惯例向读者发出信号,表明我们正在进行粗略的过度简化。 (并确保没有人错误地认为表达方式是准确的)。

    如果您将“Oh”视为“大约”或“大约”的意思,那么您就不会走得太远。 (我认为Big-Oh的选择可能是幽默的尝试。)

    这些“Big-Oh”表达式尝试做的唯一事情就是描述软件在增加软件必须处理的数据量时减慢了多少。如果我们将需要处理的数据量增加一倍,那么软件需要两倍的时间才能完成它的工作吗?十倍的时间?在实践中,你会遇到并且需要担心的大哦表达的数量非常有限:

    好处:

    •  O(1) 常量:无论输入多大,程序都会运行相同的时间。
    •  O(log n) 对数:即使输入大小大幅增加,程序运行时也只会缓慢增加。

    坏事:

    •  O(n) 线性:程序运行时间与输入大小成比例增加。
    •  O(n^k) 多项式: - 处理时间越来越快 - 作为多项式函数 - 随着输入的大小增加。

    ......丑陋的:

    •  O(k^n) 指数程序运行时间增加得非常快,即使是中等增量也是如此问题的大小 - 用指数算法处理小数据集是切实可行的。
    •  O(n!) 因子除了最小和最琐碎的数据集之外,程序运行时间将比你能够等待的时间更长。
    31
    2013-05-29 13:51:20Z
    1. 我也听说过Linearithmic - O(n log n)这个词会被认为是好的。
      2013-05-29 18:45:06Z
    2. 醇>
      

    Big O的简单英语解释是什么?尽可能少的正式定义和简单的数学。

    Big-O表示法的需要的简明英语解释:

    当我们编程时,我们正试图解决问题。我们编码的是一种算法。 Big O表示法允许我们以标准化方式比较算法的最差情况。硬件规格随时间而变化,硬件的改进可以减少算法运行所需的时间。但是替换硬件并不意味着我们的算法随着时间的推移会更好或改进,因为我们的算法仍然相同。因此,为了让我们能够比较不同的算法,以确定一个是否更好,我们使用Big O表示法。

    大O符号的简单英语解释

    并非所有算法都在相同的时间内运行,并且可能会根据输入中的项目数量而有所不同,我们称之为 n 。基于此,我们考虑更糟糕的案例分析,或者 n 越来越大的运行时上限。我们必须知道 n 是什么,因为许多Big O符号都引用它。

        
    31
    2013-10-07 14:02:21Z

    一个简单明了的答案可以是:

    Big O表示该算法的最差可能时间/空间。该算法永远不会占用超过该限制的更多空间/时间。大O代表极端情况下的时间/空间复杂性。

        
    27
    2014-03-14 16:25:08Z

    好的,我的2点。

    Big-O,是程序消耗的资源的增长率,w.r.t。问题实例尺寸

    资源:可能是总CPU时间,可能是最大RAM空间。默认情况下是指CPU时间。

    说问题是“找到总和”,

     
    int Sum(int*arr,int size){
          int sum=0;
          while(size-->0) 
             sum+=arr[size]; 
    
          return sum;
    }
    

    problem-instance = {5,10,15} ==&gt; problem-instance-size = 3,iterations-in-loop = 3

    problem-instance = {5,10,15,20,25} ==&gt; problem-instance-size = 5次迭代循环= 5

    对于大小为“n”的输入,程序以阵列中“n”次迭代的速度增长。因此,Big-O是N,表示为O(n)

    说问题是“找到组合”,

     
        void Combination(int*arr,int size)
        { int outer=size,inner=size;
          while(outer -->0) {
            inner=size;
            while(inner -->0)
              cout<<arr[outer]<<"-"<<arr[inner]<<endl;
          }
        }
    

    problem-instance = {5,10,15} ==&gt; problem-instance-size = 3,total-iterations = 3 * 3 = 9

    problem-instance = {5,10,15,20,25} ==&gt; problem-instance-size = 5,total-iterations = 5 * 5 = 25

    对于大小为“n”的输入,程序以阵列中“n * n”次迭代的速度增长。因此,Big-O是N 2 ,表示为O(n 2

        
    27
    2014-10-19 20:48:48Z
    1. while (size-->0)我希望这个不会再问了。
      2013-06-18 14:41:28Z
    2. 醇>

    Big O表示法是一种根据空间或运行时间来描述算法上限的方法。 n是数字问题中的元素(即数组的大小,树中的节点数等)我们有兴趣描述n变大的运行时间。

    当我们说某些算法是O(f(n))时,我们说该算法的运行时间(或所需空间)总是低于某些常数f(n)。

    要说二进制搜索的运行时间为O(logn),就是说存在一些常量c,你可以将log(n)乘以它常常大于二进制搜索的运行时间。在这种情况下,您将始终有一些log(n)比较的常数因子。

    换句话说,g(n)是算法的运行时间,我们说当g(n)&lt; = c * f(n)时,g(n)= O(f(n)) &GT; k,其中c和k是一些常数。

        
    25
    2010-07-17 02:29:35Z
    1. 我们可以使用BigO表示法来衡量最坏情况和平均情况。 en.wikipedia.org/wiki/Big_O_notation
      2011-09-05 16:36:05Z
    2. 醇>
      

    Big O的简单英语解释是什么?   定义尽可能简单的数学。

    这样一个非常简单和简短的问题似乎至少应该得到一个同样简短的答案,就像学生在辅导期间可能得到的那样。

      

    Big O表示法只是告诉算法可以运行多少时间,   就而言只有输入数据量 **。

    (*精彩,无单位时间感!)
    (**这是重要的,因为人们会 总是想要更多,无论他们今天还是明天都住在那里)

    嗯,如果这就是Big O符号那么精彩呢?

    • 实际上,Big O分析非常有用且重要因为Big O将重点放在算法的自己的复杂性上,完全忽略任何只是比例常数的东西 - 比如JavaScript引擎,CPU的速度,你的互联网连接,以及所有那些很快变得像模型 T 一样过时的过时的东西。 Big O只关注与现在或将来生活中的人们同等重要的表现。

    • Big O符号也直接关注计算机编程/工程这一最重要的原则,这一事实激发了所有优秀的程序员不断思考和梦想:实现超越漫长前进的结果的唯一途径技术是发明一种更好的算法

    23
    2013-08-24 06:50:03Z
    1. 被要求解释没有数学的数学问题对我来说总是个人的挑战,作为一个真正的博士学位。数学家和老师认为这样的事实际上是可能的。作为一名程序员,我希望没有人会在没有数学的情况下回答这个特殊的问题,成为一个完全不可抗拒的挑战。
      2013-08-15 02:09:07Z
    2. 醇>

    算法示例(Java):

     
    // given a list of integers L, and an integer K
    public boolean simple_search(List<Integer> L, Integer K)
    {
        // for each integer i in list L
        for (Integer i : L)
        {
            // if i is equal to K
            if (i == K)
            {
                return true;
            }
        }
    
        return false;
    }
    

    算法说明:

    • 此算法逐项搜索列表,查找密钥

    • 对列表中的每个项目进行迭代,如果是键,则返回True,

    • 如果循环已完成但未找到密钥,则返回False。

    Big-O表示法代表复杂性的上限(时间,空间,......)

    要找到Big-O on Time Complexity:

    • 计算最坏情况需要多长时间(关于输入大小):

    • 最坏情况:列表中不存在密钥。

    • 时间(最坏情况)= 4n + 1

    • 时间:O(4n + 1)= O(n)|在Big-O,常数被忽略

    • O(n)~Lineal

    还有Big-Omega,它代表了Best-Case的复杂性:

    • 最佳案例:关键是第一项。

    • 时间(最佳情况)= 4

    • 时间:Ω(4)= O(1)~Instant \Constant

    21
    2018-05-18 10:46:20Z
    1. 你的常数4来自哪里?
      2014-07-04 13:34:45Z
    2. @ Rod iterator init,迭代器比较,迭代器读取,密钥比较..我认为C会更好
      2014-07-06 11:04:55Z
    3. 醇>

    大O

    f (x)= O( g (x))当x进入a(例如,a = +∞)意味着有一个函数 k 这样:

    1. f (x)= k (x) g (x)

    2. k在某个邻域中有界(如果a = +∞,这意味着有数字N和M使得每个x> N,| k (x )|&lt; M)。

    3. 醇>

      换句话说,用简单的英语: f (x)= O( g (x)),x→a,表示在a附近, f 分解为 g 和某些有界函数的乘积。

      小o

      顺便说一下,这里是为了比较小o的定义。

      f (x)= o( g (x))当x转到a表示存在函数k时:

      1. f (x)= k (x) g (x)

      2. k (x)当x转到a时变为0.

      3. 醇>

        实施例

    • 当x→0时,sin x = O(x)。

    • sin x = O(1)当x→+∞时,

    • x 2 + x = O(x)当x→0时,

    • 当x→+∞时,
    • x 2 + x = O(x 2 ),

    • 当x→+∞时,ln(x)= o(x)= O(x)。

    注意!带有等号“=”的符号使用“假等式”:o(g(x))= O(g(x)),但是为假O(g(x))= o(g(x))。类似地,当x→+∞时写“ln(x)= o(x)是可以的,但公式”o(x)= ln(x)“没有意义。

    更多示例

    • O(1)= O(n)= O(n 2 )当n→+∞时(但不是相反,等式是“假的”),

    • O(n)+ O(n 2 )= O(n 2 )当n→+∞

    • O(O(n 2 ))= O(n 2 )当n→+∞

    • O(n 2 )当n→+∞时,O(n 3 )= O(n 5


    以下是维基百科的文章: https://en.wikipedia.org/wiki/Big_O_notation

        
    18
    2014-10-19 20:50:47Z
    1. 你说的是“大O”和“小o”,没有解释它们是什么,引入了大量的数学概念而没有说明它们为什么重要,而且维基百科的链接可能是在这种情况下,对于这类问题来说太明显了。
      2014-01-11 14:54:41Z
    2. @ AditSaxena你的意思是“没有解释它们是什么”?我完全解释了它们是什么。也就是说,“大O”和“小o”本身并不是什么,只有像“f(x)= O(g(x))”这样的公式具有含义,我解释过(用简单的英语,但没有定义)当然,微积分课程中所有必要的东西)。有时“O(f(x))”被视为所有函数“g(x)”的类(实际上是集合),使得“g(x)= O(f(x))”,但这是一个额外的步骤,这对理解基础知识不是必需的。
      2014-01-11 18:34:54Z
    3. 嗯,好吧,有些单词不是简单的英语,但它是不可避免的,除非我必须包括数学分析中的所有必要定义。
      2014-01-11 18:38:21Z
    4. 嗨#Alexey,请看看已接受的答案r:它很长但是它构造得很好并且格式很好。它以简单的定义开始,不需要数学背景。在这样做的同时,他引入了3个“技术”词,他立即解释(相对,表现,复杂)。这一过程一步一步地深入到这个领域。
      2014-01-12 22:44:07Z
    5. Big O用于理解算法的渐近行为,原因与它用于理解函数的渐近行为(渐近行为是无穷远附近的行为)相同。这是一个方便的符号,用于比较复杂函数(算法采用的实际时间或空间)与无穷大附近或其他任何附近的简单函数(任何简单的,通常是幂函数)。我只解释了它是什么(给出了定义)。如何用大O计算是一个不同的故事,也许我会添加一些例子,因为你感兴趣。
      2014-01-13 17:23:47Z
    6. 醇>

    Big O表示法是一种描述算法在给定任意数量的输入参数下运行的速度的方法,我们将其称为“n”。它在计算机科学中很有用,因为不同的机器以不同的速度运行,并且简单地说算法需要5秒钟并不能告诉你太多,因为当你运行一个带有4.5 Ghz八核处理器的系统时,我可能正在运行一个15岁的800 Mhz系统,无论算法如何,都可能需要更长的时间。因此,我们不是指定算法在时间上运行的速度,而是根据输入参数的数量或“n”来说它运行的速度有多快。通过以这种方式描述算法,我们能够比较算法的速度,而不必考虑计算机本身的速度。

        
    18
    2015-05-12 14:02:34Z

    不确定我是否正在为这个问题做出进一步的贡献,但仍然认为我会分享:我曾经发现这篇博客文章有一些非常有帮助的(虽然非常基本的)解释&amp; Big O的例子:

    通过例子,这有助于将基本的基本部分放入我的玳瑁般的头骨中,所以我认为这是一个非常下降的10分钟阅读,让你朝着正确的方向前进。

        
    11
    2013-01-15 20:23:20Z
    1. @ William ...人们往往会死于老年,物种灭绝,行星变得贫瘠等等。
      2013-05-30 05:52:12Z
    2. 醇>

    你想知道大O的所有知识吗?我也是。

    所以谈到大O,我将使用只有一个节拍的单词。每个单词一个声音。小词很快。你知道这些话,我也一样。我们会用一个声音的单词。他们很小。我相信你会知道我们将使用的所有词语!

    现在,让我们和你谈谈工作。大多数时候,我不喜欢工作。你喜欢上班吗?你可能会这样,但我相信我没有。

    我不喜欢去上班。我不喜欢在工作上花时间。如果我有自己的方式,我只想玩,做有趣的事情。你觉得和我一样吗?

    现在有时,我必须去上班。这很难过,但却是真的。所以,当我在工作时,我有一个规则:我尝试做更少的工作。我尽可能无法工作。然后我去玩!

    所以这是个大新闻:大O可以帮助我不做工作!我可以玩更多的时间,如果我知道大O.少工作,多玩!这就是大O帮助我做的事情。

    现在我有一些工作。我有这个清单:一,二,三,四,五,六。我必须在此列表中添加所有内容。

    哇,我讨厌工作。但是哦,我必须这样做。所以我走了。

    一加二是三......加三是六......四是......我不知道。我迷路了。我脑子里很难做到这一点。我不太喜欢是为了这种工作。

    所以,让我们不做这项工作。让我和你思考它有多难。我需要做多少工作才能添加六个数字?

    嗯,让我们看看。我必须添加一个和两个,然后将其添加到三个,然后将其添加到四个...总而言之,我计算六个添加。我必须做六个补充来解决这个问题。

    这里有大O,告诉我们这个数学有多难。

    Big O说:我们必须做六个补充来解决这个问题。一个补充,每个东西从一到六。六个小工作......每一项工作都是一个补充。

    好吧,我现在不会去做它们的工作。但我知道它会有多难。这将是六个补充。

    哦不,现在我有更多的工作。啧。谁做这种东西?!

    现在他们要我加一到十!我为什么要这么做?我不想添加一到六个。从一到十加......好吧......那会更难!

    它会变得多难?我还需要做多少工作?我需要更多或更少的步骤吗?

    好吧,我想我必须做十次补充......一次从一到十次。十分超过六分。我需要做更多工作,从一到十,而不是一到六!

    我现在不想添加。我只是想想加入那么多可能有多难。并且,我希望,尽快发挥。

    要从一到六添加,这是一些工作。但是你知道,从一到十加上,这是更多的工作吗?

    Big O是你的朋友和我的朋友。 Big O帮助我们思考我们需要做多少工作,所以我们可以计划。而且,如果我们是大O的朋友,他可以帮助我们选择不那么难的工作!

    现在我们必须做新工作。不好了。我根本不喜欢这件事。

    新工作是:将所有内容从一个添加到n。

    等待!什么是n?我错过了吗?如果你不告诉我什么是n,我如何从一个添加到n?

    好吧,我不知道n是什么。我没有被告知。是吗?没有?那好吧。所以我们不能做这项工作。呼。

    但是,虽然我们现在不会做这项工作,但如果我们知道的话,我们可以猜到它会有多难。我们必须加起来,对吗?当然!

    现在这里有大O,他会告诉我们这项工作有多难。他说:将所有东西从一个添加到N,一个接一个,是O(n)。要添加所有这些东西,[我知道我必须添加n次。] [1]那是大O!他告诉我们做某种工作有多难。

    对我而言,我认为大O就像一个又大又慢的老板。他在工作上思考,但他没有这样做。他可能会说,“这项工作很快。”或者,他可能会说,“这项工作是如此缓慢而艰难!”但他不做这项工作。他只看工作,然后告诉我们可能需要多长时间。

    我非常关心大O.为什么?我不喜欢上班!没有人喜欢工作。这就是为什么我们都喜欢大O!他告诉我们我们的工作速度有多快。他帮助我们思考工作是多么努力。

    哦,哦,更多的工作。现在,我们不做这项工作。但是,让我们一步一步地制定计划。

    他们给了我们一张十张牌。他们都混在一起:七,四,二,六......根本不直。而现在......我们的工作就是对它们进行分类。

    Ergh。这听起来像是很多工作!

    我们怎样才能对这个套牌进行排序?我有个计划。

    我将从头到尾看着每对卡片,一副一对地穿过甲板。如果一对中的第一张卡很大而且该对中的下一张卡很小,我会换掉它们。否则,我会去下一对,依此类推......很快,甲板就完成了。

    当牌组完成后,我问:我是否在那张传球中换了牌?如果是这样,我必须从顶部再一次完成。

    在某些时候,某个时候,将不会进行掉期交易,而且我们的甲板将会完成。这么多工作!

    那么,根据这些规则对牌进行排序会有多少工作?

    我有十张牌。而且,大部分时间 - 也就是说,如果我没有很多运气 - 我必须通过整个套牌十次,每次通过套牌最多十次换卡。

    大O,帮助我!

    Big O进来并说:对于一副n张牌,这样排序将以O(N平方)时间完成。

    为什么他说n平方?

    嗯,你知道n平方是n次n。现在,我得到它:n卡检查,直到可能是通过甲板n次。这是两个循环,每个循环有n个步骤。这是很多工作要做的事情。很多工作,当然!

    现在,当大O说它将需要O(n平方)工作时,他并不意味着n平方加在鼻子上。在某些情况下,它可能会少一些。但在最糟糕的情况下,它将接近n平方的工作量来对甲板进行分类。

    现在,大O是我们的朋友。

    Big O指出这一点:随着n变得越来越大,当我们对卡片进行分类时,这项工作比旧的只是添加这些工作要困难得多。我们怎么知道这个?

    好吧,如果n变得很大,我们就不在乎了我们可能添加到n或n平方。

    对于大n,n平方比n大。

    Big O告诉我们,对东西进行排序比添加东西更难。对于大n,O(n平方)大于O(n)。这意味着:如果n变得非常大,那么对n个东西进行排序必须花费更多时间,而不是仅添加n个混合物。

    Big O无法为我们解决问题。 Big O告诉我们工作有多难。

    我有一副纸牌。我对它们进行了排序。你帮忙了感谢。

    有没有更快捷的方式对牌进行排序?大O可以帮助我们吗?

    是的,还有更快的方法!这需要一些时间来学习,但它的工作原理......它的工作速度非常快。您也可以尝试,但每走一步都要花时间,不要失去你的位置。

    在这种对甲板进行分类的新方法中,我们不像前一段时间那样检查成对的牌。以下是您对此套牌进行排序的新规则:

    一:我现在在甲板上选择一张牌。如果你愿意,你可以选择一个。 (我们第一次这样做,“我们现在处理的甲板部分”当然是整个甲板。)

    二:我在您选择的那张牌上张开了牌组。这是什么意思;我该如何施展?好吧,我一个接一个地从开始卡开始,我找到一张比插卡更高的卡片。

    三:我从终端卡开始,我寻找一张比张卡更低的卡片。

    一旦我找到了这两张牌,我就换掉它们,继续寻找更多牌来换掉。也就是说,我回到第二步,然后在你选择的卡上张开更多。

    在某些时候,这个循环(从2到3)将结束。当此搜索的两半在展开卡处相遇时结束。然后,我们刚刚用你在第一步中选择的牌张开了牌组。现在,开始附近的所有卡都比低位卡更低;并且靠近末端的卡比展开的卡更高。很酷的技巧!

    四(这是有趣的部分):我现在有两个小甲板,比展开卡低一个,还有一个高。现在我走到每个小甲板上的第一步!也就是说,我从第一个小甲板上的第一步开始,当这项工作完成后,我从下一个小甲板上的第一步开始。

    我将甲板分成几部分,然后对每个部分进行分类,更小,更小,有时候我没有更多的工作要做。现在这可能看起来很慢,包含所有规则。但请相信我,它根本不慢。它比第一种排序方式要少得多!

    这叫什么?它被称为快速排序!那种叫做 C. A. R. Hoare 他称之为快速排序。现在,Quick Sort一直在使用!

    快速排序打破小型甲板。也就是说,它打破了小任务中的大任务。

    嗯。我认为可能存在规则。为了使大任务变小,请将其分解。

    这种很快。多快? Big O告诉我们:在这种情况下,这种类型需要完成O(n log n)工作。

    它比第一种更快还是更快?大O,请帮忙!

    第一种是O(n平方)。但快速排序是O(n log n)。你知道n log n小于n平方,对于大n,对吗?好吧,这就是我们知道快速排序很快的方法!

    如果你必须对甲板进行排序,那么最好的方法是什么?好吧,你可以做你想做的事,但我会选择快速排序。

    为什么选择快速排序?当然,我不喜欢工作!我希望我能尽快完成工作。

    我如何知道快速排序的工作量较少?我知道O(n log n)小于O(n平方)。 O更小,因此Quick Sort工作量更少!

    现在你认识我的朋友Big O.他帮助我们减少工作量。如果你知道大O,你也可以做更少的工作!

    你跟我学到了这一切!你太聪明了!非常感谢你!

    现在工作已经完成,让我们去玩吧!


    [1]:有一种方法可以欺骗并将所有东西从一个添加到n,所有这些都是一次性的。一个名叫高斯的小孩在八岁的时候发现了这个。我不是那么聪明,所以不要问我是怎么做的。

        
    11
    2016-03-10 23:03:36Z

    假设我们正在谈论一个算法 A ,它应该对大小 n 的数据集做一些事情。

    然后O( <some expression X involving n> )表示,用简单的英语:

      

    如果你在执行A时不走运,可能需要执行X(n)操作   完整。

    碰巧,有某些功能(将它们视为 X(n)的实现,往往经常发生。这些是众所周知的,很容易比较(例如:1,Log N,N,N^2,N!等。)

    通过在讨论 A 和其他算法时对这些进行比较,很容易根据可能(最坏情况)所需的操作次数对算法进行排名完成。

    一般来说,我们的目标是找到或构建算法 A ,使其具有尽可能低的数字返回的函数X(n)

        
    9
    2013-10-25 15:11:17Z

    我有更简单的方法来理解时间复杂性 计算时间复杂度的最常见指标是Big O表示法。这消除了所有常数因子,因此当N接近无穷大时,可以相对于N估计运行时间。一般来说,你可以这样想:

     
    statement;
    

    是不变的。语句的运行时间不会相对于N

    而改变  
    for ( i = 0; i < N; i++ )
      statement;
    

    是线性的。循环的运行时间与N成正比。当N加倍时,运行时间也是如此。

     
    for ( i = 0; i < N; i++ ) 
    {
    for ( j = 0; j < N; j++ )
      statement;
    }
    

    是二次的。两个循环的运行时间与N的平方成正比。当N加倍时,运行时间增加N * N.

     
    while ( low <= high ) 
    {
     mid = ( low + high ) / 2;
     if ( target < list[mid] )
     high = mid - 1;
     else if ( target > list[mid] )
      low = mid + 1;
    else break;
    }
    

    是对数的。算法的运行时间与N除以2的次数成正比。这是因为算法在每次迭代时将工作区域分成两半。

     
    void quicksort ( int list[], int left, int right )
    {
      int pivot = partition ( list, left, right );
      quicksort ( list, left, pivot - 1 );
      quicksort ( list, pivot + 1, right );
    }
    

    N * log(N)。运行时间由N个循环(迭代或递归)组成,这些循环是对数的,因此算法是线性和对数的组合。

    一般来说,对一个维度中的每个项目执行某些操作是线性的,对二维中的每个项目执行某些操作是二次的,将工作区域分成两半是对数的。还有其他Big O指标,如立方,指数和平方根,但它们并不常见。 Big O表示法被描述为O(),其中是度量。快速排序算法将被描述为O(N * log(N))。

    注意:这些都没有考虑最佳,平均和最坏情况的措施。每个都有自己的Big O表示法。另请注意,这是一个非常简单的解释。 Big O是最常见的,但它也显示得更复杂。还有其他符号,如大欧米茄,小o和大theta。您可能不会在算法分析课程之外遇到它们。

    9
    2015-09-15 13:52:39Z

    说你订购哈利波特:从亚马逊完成8-Film Collection [Blu-ray]并同时在线下载相同的电影收藏。您想测试哪种方法更快。交付大约需要一天到达,下载大约提前30分钟完成。大!所以这是一场紧张的比赛。

    如果我订购了诸如指环王,暮光之城,黑暗骑士三部曲等多部蓝光电影,并同时在线下载所有电影,该怎么办?这一次,交付仍需要一天时间才能完成,但在线下载需要3天才能完成。 对于在线购物,购买的商品数量(输入)不会影响交货时间。输出是不变的。我们称之为 O(1)

    对于在线下载,下载时间与电影文件大小(输入)成正比。我们称之为 O(n)

    从实验中,我们知道网上购物比在线下载更好。理解大O表示法非常重要,因为它可以帮助您分析算法的可伸缩性效率

    注意: Big O表示法表示算法的最坏情况。我们假设 O(1) O(n)是上述示例的最坏情况。

    参考 http://carlcheo.com/compsci

        
    9
    2015-12-06 06:01:13Z
    四>

    如果你头脑中有一个合适的无限概念,那么就有一个非常简短的描述:

      

    Big O表示法告诉您解决无限大问题的成本。

    此外

      

    常数因素可以忽略不计

    如果升级到能够以两倍的速度运行算法的计算机,则大O表示法不会注意到这一点。恒定因子的改进太小,甚至在大O符号的工作范围内都没有被注意到。请注意,这是大O符号设计的有意部分。

    然而,虽然可以检测到比常数因子“更大”的任何东西。

    当有兴趣进行大小“足够大”的计算时,那么大O符号大约是解决问题的成本。


    如果上述内容没有意义,那么你的头脑中没有兼容的直观无限概念,你应该忽视以上所有内容;我所知道的唯一方法是使这些想法严格,或者解释它们,如果它们还没有直观的用处,那就是首先教你大O符号或类似的东西。 (虽然,一旦你很好地理解了未来的大O符号,重新考虑这些想法可能是值得的)

        
    8
    2015-05-16 16:02:02Z
      

    “Big O”符号的简单英语解释是什么?

    非常快速注意:

    “大O”中的O指的是“顺序”(或恰恰是“顺序”)
    所以你可以从字面上理解它用来订购比较它们的东西。

    • “Big O”有两件事:

      1. 估算计算机应用于完成任务的方法步数。
      2. 促进流程与其他流程进行比较以确定其是否良好?
      3. “Big O”使用标准化的Notations实现上述两项。
      4. 醇>
    • 有七种最常用的符号

      1. O(1),表示您的计算机完成了1步骤完成的任务,非常好,订购1号
      2. O(logN),表示您的计算机完成了logN步骤的任务,其良好,订购号为2
      3. O(N),完成任务N步,公平,订单3
      4. O(NlogN),以O(NlogN)步结束任务,不太好,订单No.4
      5. O(N ^ 2),用N^2步完成一项任务,这很糟糕,订单号为5
      6. O(2 ^ N),用2^N步完成任务,这太可怕了,订单No.6
      7. O(N!),用N!步完成任务,很糟糕,订单号7
      8. 醇>

    假设你得到了符号O(N^2),不仅你清楚该方法需要N * N个步骤才能完成一项任务,你也会发现它的排名不如O(NlogN)

    请注意行尾的顺序,以便您更好地理解。如果考虑所有可能性,则有超过7种符号。

    在CS中,完成任务的一组步骤称为算法 在术语中,Big O表示法用于描述算法的性能或复杂性。

    此外,Big O建立最坏情况或测量上限步骤 您可以参考Big-Ω(Big-Omega)获得最佳案例。

    Big-Ω( Big-Omega)符号(文章)|可汗学院

    • 摘要强>结果 “Big O”描述了算法的性能并对其进行了评估。

      或正式解决,“Big O”对算法进行分类并使比较过程标准化。

    7
    2018-04-13 13:53:42Z

    最简单的查看方法(用简单的英语)

    我们正在尝试查看输入参数的数量,如何影响算法的运行时间。如果应用程序的运行时间与输入pa的数量成正比rameter,然后它据说在n的大O.

    上述陈述是一个良好的开端,但并非完全正确。

    更准确的解释(数学)

    假设

    n =输入参数的数量

    T(n)=表示算法运行时间的实际函数,作为n

    的函数

    c =常数

    f(n)=一种近似函数,表示算法的运行时间是n

    的函数

    然后就Big O而言,只要满足以下条件,近似f(n)就足够了。

     
    lim     T(n) ≤ c×f(n)
    n→∞
    

    方程式读作 当n接近无穷大时,n的T小于或等于n的c倍f。

    在大O符号中,这写为

     
    T(n)∈O(n)
    

    这是因为n的t在n的大O中。

    返回英语

    根据上面的数学定义,如果你说你的算法是n的大O,那就意味着它是n(输入参数的数量)或更快的函数。如果你的算法是n的大O,那么它也自动是n平方的大O.

    n的大O意味着我的算法运行至少与此一样快。您无法查看算法的Big O表示法,并说它很慢。你只能说它快。

    查看视频中的加州大学伯克利分校的Big O教程。这实际上是一个简单的概念。如果你听到Shewchuck教授(又名神级教师)解释它,你会说“哦,就是这样!”。

        
    6
    2016-09-15 14:15:12Z

    我发现了一个关于大O符号的非常好的解释,特别是对于一个对数学不太了解的人。

    https://rob- bell.net/2009/06/a-beginners-guide-to-big-o-notation/

      

    计算机科学中使用Big O表示法来描述性能   或算法的复杂性。 Big O专门描述了   最糟糕的情况,可以用来描述执行时间   所需的或所用的空间(例如在内存或磁盘上)由   算法

         

    任何阅读编程珍珠或任何其他计算机科学的人   书籍并没有数学基础就会碰壁   当他们到达提及O(N log N)或其他似乎的章节时   疯狂的语法。希望这篇文章能帮助你获得一个   理解Big O和Logarithms的基础知识。

         

    作为程序员第一,数学家第二(或者第三或第二)   第四)我找到了彻底了解Big O的最好方法   在代码中产生一些例子。所以,下面是一些常见的订单   增长以及可能的描述和示例。

         

    O(1)

         

    O(1)描述了一种始终在同一时间执行的算法   (或空格),与输入数据集的大小无关。

     
    bool IsFirstElementNull(IList<string> elements) {
        return elements[0] == null; } O(N)
    
         

    O(N)

         

    O(N)描述了一种算法,其性能将线性增长   与输入数据集的大小成正比。这个例子   下面还演示了Big O如何倾向于最坏情况的表现   场景;在任何迭代期间都可以找到匹配的字符串   for循环,函数会提前返回,但Big O表示法会返回   总是假设算法将执行的上限   最大迭代次数。

     
    bool ContainsValue(IList<string> elements, string value) {
        foreach (var element in elements)
        {
            if (element == value) return true;
        }
    
        return false;
    } 
    
         

    O(N 2

         

    O(N 2 )表示直接表现的算法   与输入数据集大小的平方成正比。这是   与涉及数据嵌套迭代的算法相同   组。更深的嵌套迭代将导致O(N 3 ),O(N 4 )等。

     
    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(2 Ñ

         

    O(2 N )表示一种算法,其增长率随着每个附加值的增加而翻倍   输入数据集。 O(2 N )函数的生长曲线是   指数 - 从非常浅的开始,然后迅速上升。一个   O(2 N )函数的一个例子是Fibonacci的递归计算   数:

     
    int Fibonacci(int number) {
        if (number <= 1) return number;
    
        return Fibonacci(number - 2) + Fibonacci(number - 1);
    }
    
         

    对数

         

    对数稍微复杂一点,所以我会使用一个常见的   例如:

         

    二进制搜索是一种用于搜索已排序数据集的技术。有用   通过选择数据集的中间元素,基本上是   中位数,并将其与目标值进行比较。如果值与之匹配   将返回成功。如果目标值高于值   探针元素将占据数据集的上半部分   对它执行相同的操作。同样,如果是目标值   低于它将执行的探测元素的值   对下半部分的操作。它将继续将数据减半   设置每次迭代,直到找到值或直到找到值   不再拆分数据集。

         

    这种算法被描述为O(log N)。迭代减半   二进制搜索示例中描述的数据集产生增长   曲线在开始时达到峰值,并随着大小逐渐变平   例如,数据集增加了包含10个项目的输入数据集   需要一秒钟才能完成,包含100个项目的数据集   两秒钟,包含1000个项目的数据集将占用三个   秒。加倍输入数据集的大小几乎没有影响   它的增长是在算法的单次迭代之后的数据集   将减半,因此与输入数据集的一半相同   尺寸。这使得二进制搜索等算法非常有效   在处理大型数据集时。

        
    5
    2018-10-31 17:47:18Z

    这是一个非常简化的解释,但我希望它涵盖了最重要的细节。

    假设您处理问题的算法取决于某些“因素”,例如让我们将其设为N和X.

    根据N和X,您的算法将需要一些操作,例如在最坏情况下它是3(N^2) + log(X)操作。

    由于Big-O并不太关心常数因子(又称3),因此算法的Big-O为O(N^2 + log(X))。它基本上可以转换'算法在最坏情况下需要的操作量'。

        
    4
    2015-10-11 18:00:20Z

    定义: - Big O表示法表示如果数据输入增加,算法性能将如何执行。

    当我们谈论算法时,有三个重要的支柱输入,输出和处理算法。 Big O是符号表示法,表示如果数据输入增加的话,算法处理的性能会有多大差异。

    我建议您观看此YouTube视频,其中介绍了 Big O Notation 深度与代码示例。

    因此,例如假设算法需要5条记录,处理相同的时间为27秒。现在,如果我们将记录增加到10,算法需要105秒。

    简单来说,所花费的时间是记录数的平方。我们可以用 O(n ^ 2)来表示这一点。这种符号表示被称为Big O符号。

    现在请注意单位可以是任何输入,它可以是字节,位数记录,性能可以在任何单位测量,如秒,分钟,天等。所以它不是确切的单位,而是关系。

    例如,查看下面的函数“Function1”,它接受一个集合并对第一条记录进行处理。现在,对于此功能,无论您输入1000,10000或100000记录,性能都是相同的。所以我们可以用 O(1)来表示它。

     
    void Function1(List<string> data)
    {
    string str = data[0];
    }
    

    现在看下面的函数“Function2()”。在这种情况下,处理时间将随着记录的数量而增加。我们可以使用 O(n)来表示这种算法性能。

     
    void Function2(List<string> data)
            {
                foreach(string str in data)
                {
                    if (str == "shiv")
                    {
                        return;
                    }
                }
            }
    

    当我们看到任何算法的Big O表示法时,我们可以将它们分为三类表现: -

    1. 日志和常量类别: - 任何开发人员都希望在此类别中看到他们的算法性能。
    2. 线性: - 开发人员不希望看到此类别中的算法,直到最后一个选项或唯一选项为止。
    3. 指数: - 这是我们不希望看到我们的算法并且需要返工的地方。
    4. 醇>

      所以l在Big O表示法中,我们将算法的好区和坏区分类。

      我建议你观看这个10分钟的视频,其中讨论Big O的示例代码

      https://www.youtube.com/watch?v=k6kxtzICG_g

          
    4
    2018-05-11 09:43:53Z
来源放置 这里