为什么大哦并不总是算法的最坏情况分析?

时间:2018-04-16 03:16:51

标签: algorithm data-structures time-complexity complexity-theory

我正在尝试学习算法分析,我对asymptotic notation(大O ...)和cases(最佳,最差和平均)之间的关系感到困惑。

我知道Big O符号定义了算法的上界,即它定义的函数不能超过其上限。

起初它听起来像是在计算最坏的情况。 我谷歌(为什么最坏的情况不是大O?)并得到了大量的答案,这些答案对于初学者来说并不是那么容易理解。

我的结论如下: Big O并不总是用于表示算法的最坏情况分析,因为假设一个算法采用O(n)执行步骤来获得最佳,平均和最差输入,那么它的最佳,平均和最差情况可以表示为O( n)中。

请告诉我,如果我是正确的,或者我遗失了一些东西,因为我没有任何人可以证实我的理解。 请提供一个更好的示例,以了解为什么Big O并非总是worst case

6 个答案:

答案 0 :(得分:2)

两者不是一回事。其他人所说的最坏情况分析是识别算法花费最长时间完成的实例(即,采用最多步骤),然后使用此算法制定生长函数。人们可以使用Big-Oh,甚至其他变体(如Big-Omega和Big-Theta)分析最坏情况下的时间复杂度(实际上,Big-Theta通常是你想要的,尽管经常使用Big-Oh来方便那些不那么理解的人的理解)。一个重要的细节和最坏情况分析有用的原因是算法的运行速度不会比最坏的情况慢。最坏情况分析是我们在分析算法时使用的分析方法。

Big-Oh本身是增长函数的渐近量度;这可以是完全独立的,因为人们可以使用Big-Oh甚至不测量算法的时间复杂度;它的起源源于数论。你说它是增长函数的渐近上界是正确的;但是您开出和构建增长函数的方式来自您的分析。增长函数的Big-Oh本身在没有上下文的情况下几乎没有任何意义,因为它只能说明您正在分析的函数。请记住,可以构建无限多的算法来共享相同的时间复杂度(通过Big-Oh的定义,Big-Oh是一组增长函数)。

简而言之,最坏情况分析是你如何建立你的成长函数,Big-Oh表示法是分析所述增长函数的一种方法。然后,我们可以将该结果与针对给定问题的竞争算法的其他最坏情况时间复杂度进行比较。如果正确完成,最坏情况分析会产生最坏情况下的运行时间(如果使用气压计,可以削减很多角并仍然获得正确的渐近),并且使用此增长函数会产生最坏情况的时间复杂度算法。仅仅大哦不能保证最坏情况下的时间复杂性,因为你必须自己实现增长功能。例如,我可以将Big-Oh表示法用于任何其他类型的分析(例如,最佳情况,平均情况)。这真的取决于你想要捕捉的东西。例如,Big-Omega非常适合下限。

想象一个假设的算法,在最好的情况下只需要做1步,在最坏的情况下需要做n2步,但在平均(预期)的情况下,只需要做n步。 n是输入大小。 对于这3种情况中的每一种,您都可以计算出描述该算法时间复杂度的函数。     1最好的情况有O(1),因为函数f(x)= 1实际上是我们可以去的最高,但也是我们可以在这种情况下最低的,omega(1)。由于Omega等于O(上限和下限),我们声明这个函数在最好的情况下表现得像theta(1)。     2我们可以对最坏情况做同样的分析,并找出O(n2)= omega(n2)= theta(n2)。     3平均情况相同,但使用theta(n)。 所以在理论上你可以确定3个算法的情况,并且对于这3个案例计算下/上/后界限。我希望这可以解决一些问题。

  

https://www.google.co.in/amp/s/amp.reddit.com/r/learnprogramming/comments/3qtgsh/how_is_big_o_not_the_same_as_worst_case_or_big/

答案 1 :(得分:1)

Big O表示法显示算法相对于输入大小的增长情况。它没有说明哪种算法更快,因为它没有考虑到恒定的设置时间(如果你有小的输入大小,它可以占主导地位)。所以当你说

  

采用O(n)执行步骤

这几乎没有任何意义。 Big O没有说明有多少执行步骤。有C + O(n)步(其中C是常数),并且该算法根据输入大小以n的速率增长。

Big O可用于最佳,最差或平均情况。我们以排序为例。冒泡排序是一种天真的O(n ^ 2)排序算法,但是当列表被排序时,它需要O(n)。 Quicksort通常用于排序(GNU标准C库使用它进行一些修改)。它在O(n log n)处预先形成,但是仅当所选择的枢轴将阵列分成两个相等大小的块(平均)时才会这样。在最坏的情况下,我们在枢轴的一侧获得一个空数组,而Quicksort在O(n ^ 2)处执行。

由于Big O显示算法如何在大小方面增长,您可以查看算法的任何方面。最佳情况,平均情况,时间和/或内存使用情况最差的情况。它告诉你当输入大小增长时它们是如何增长的 - 但它并没有说哪个更快。

如果您处理的是小尺寸,那么Big O无关紧要 - 但是分析可以告诉您当输入尺寸增加时情况将会如何。

答案 2 :(得分:1)

最坏情况可能不是渐近限制的一个示例:假设您有一个算法可以处理某些集合和输入之间的集合差异。它可能在 O N )时间内运行,但随着输入变大并从工作集中敲出更多值,它会变得更快。

或者,为了获得更抽象, f x )= 1 / x x > 0是递减 O (1)函数。

答案 3 :(得分:1)

我将时间作为一个相当常见的兴趣项目,但Big-O也可用于评估资源需求,如内存。您必须意识到Big-O告诉问题的运行时或资源需求(渐近地)如何随着问题规模的增加而增加。 可以预测所需的实际时间。预测实际运行时间需要我们知道预测公式中的常量和低阶项,这取决于硬件,操作系统,语言,编译器等。使用Big-O可以让我们在回避所有的时候讨论算法行为那些依赖。

让我们来谈谈如何使用一些示例来解释Big-O可伸缩性。如果问题是O(1),则无论问题大小如何,都需要相同的时间。这可能是一个纳秒或一千秒,但在极限增加或三倍的问题的大小不会改变时间。如果问题是O(n),则问题大小加倍或三倍将(渐近地)分别使所需时间量增加一倍或三倍。如果问题是O(n ^ 2),那么问题大小加倍或三倍将(渐近地)分别花费4或9倍。等等...

许多算法针对最佳,平均或最差情况具有不同的性能。排序提供了一些相当简单的例子,说明最佳,平均和最差案例分析可能有何不同。

我假设您知道insertion sort是如何运作的。在最坏的情况下,列表可以是反向排序的,在这种情况下,对于所有项目,每个过程必须将当前正在考虑的值移动到尽可能远的左侧。这产生O(n ^ 2)行为。将列表大小加倍将花费四倍的时间。更可能的是,输入列表是随机顺序的。在这种情况下,平均每个项目必须向列表前面移动一半的距离。这比最坏的情况要少,但只是一个常数。它仍然是O(n ^ 2),因此对随机列表进行排序的次数是我们的第一个随机列表的两倍,平均需要的时间量将翻两番。它会比最坏的情况更快(由于所涉及的常数),但它以相同的方式缩放。然而,最好的情况是列表已经排序。在这种情况下,你检查每个项目,看它是否需要向前滑动,并立即找到答案是"不,"所以在检查了你在O(n)时间内完成的每个n值之后。因此,对已经排序的列表使用插入排序只需要两倍大小而不是四倍长。

答案 4 :(得分:1)

大O?

首先让我们看看Big O正式意味着什么:

  

在计算机科学中,大O符号用于对算法进行分类   根据他们的运行时间或空间要求如何增长   输入大小增加。

这意味着,Big O表示法根据其增长率来表征函数:具有相同增长率的不同函数可以使用相同的O表示法来表示。这里,O表示函数的顺序,它只对函数的增长率提供上限

现在让我们看看Big O的规则:

  • 如果f(x)是几个项的总和,如果有一个最大的项 增长率,可以保留,所有其他省略
  • 如果f(x)是几个因子的乘积,那么任何常数(项中的项) 可以省略不依赖于x)的产品。

示例:

f(x)= 6x ^ 4 - 2x ^ 3 + 5

使用第一条规则我们可以把它写成,f(x)= 6x ^ 4

使用第二条规则,它会给我们,O(x ^ 4)

什么是最差情况

  

最差案例分析给出了最大的基本操作数   必须在执行算法期间执行。它假定   输入处于最糟糕的状态,最大限度的工作必须   要把事情做好。

例如,对于旨在按升序对数组进行排序的排序算法,最坏的情况发生在输入数组按降序排列时。在这种情况下,必须进行最大数量的基本操作(比较和分配)以按升序设置数组。

这取决于很多事情:

  • CPU(时间)使用
  • 内存使用
  • 磁盘使用情况
  • 网络使用

有什么区别?

Big-O通常用于生成有关测量算法最坏情况行为的函数的语句,但big-O表示法并不意味着任何类型的行为。

这里重要的一点是我们谈论的是增长,而不是运营的数量。但是,对于算法,我们会讨论相对于输入大小的操作数。

Big-O用于声明函数。这些功能可以测量岛上的时间或空间或缓存未命中或兔子或任何或任何东西。 Big-O表示法并不关心。

事实上,当用于算法时,big-O几乎从不是时间。这是关于原始操作的。

当有人说MergeSort的时间复杂度为O(nlogn)时,它们通常意味着MergeSort进行的比较次数为O(nlogn)。这本身并没有告诉我们任何特定MergeSort的时间复杂性可能是什么,因为这将取决于进行比较所需的时间。换句话说,O(nlogn)将比较称为原始操作。

这里重要的一点是,当big-O应用于算法时,总会有一个潜在的计算模型。 MergeSort的时间复杂度为O(nlogn)的主张隐含地引用了一种计算模型,其中比较需要恒定的时间而其他一切都是免费的。

示例 -

如果我们要对长度为kk字节的字符串进行排序,我们可能会将“读取一个字节”作为一个基本操作,在其他所有内容都空闲的情况下需要一段时间。

在这个模型中,MergeSort进行O(nlogn)字符串比较,每个比较都进行O(k)字节比较,因此时间复杂度为O(k⋅nlogn)。 RadixSort的一个常见实现是使k遍历n个字符串,每个遍读取一个字节,因此时间复杂度为O(nk)。

答案 5 :(得分:1)

你是对的,你可以肯定地说,算法在最佳或平均情况下以 O(f(n))时间运行。我们一直这样做,例如,快速排序,平均 O(N log N),但只有 O(N ^ 2)最坏的情况。

但是,除非另有说明,否则当您说算法在 O(f(n))时运行时,您说该算法在 O(f(n))中运行时间在最坏的情况下。至少应该是这样的。有时候人们变得草率,你会经常听到哈希表是 O(1),而在最坏的情况下它实际上更糟糕。

大O定义无法表征最坏情况的另一种方式是它只是上限 O(N)中的任何函数 O(N ^ 2) O(2 ^ N),所以我们完全正确地说快速排序需要 O(2 ^ N)时间。我们不会这么说,因为这样做并不是很有用。

Big Theta和Big Omega分别指定下限和下限。