【问题标题】:Are asymptotic notations flawed?渐近符号有缺陷吗?
【发布时间】:2021-05-06 00:24:24
【问题描述】:

任何算法的最佳情况复杂度是算法完成其任务所需的最短时间。我们知道合并排序、快速排序等算法的最佳情况复杂度是 Ω(n log(n)),它定义了这些算法的下限。

我们知道,在渐近符号中 -

O(n) + O(n log(n)) = O(n log(n))

还有,

Ω(n) + Ω(n log(n)) = Ω(n log(n))

因此,如果在这些排序算法中,我们首先在 O(n) 时间内遍历整个数组,以确定该数组是否已经按升序或降序排序,那么它们的平均情况和最坏情况复杂度将渐近保持不变.但他们最好的情况复杂度现在将变为 Ω(n)

从逻辑上讲,我理解这些渐近符号的方式肯定存在缺陷,否则当渐近符号正在开发或流行用于度量排序算法时,肯定有人会指出这一点。我是否正确地假设这是渐近符号中的一个似是而非的缺陷,还是我错过了一些渐近符号规则?

【问题讨论】:

  • “我们知道[比较排序]算法的最佳情况复杂度......是O(n log(n))”实际上是最好的 b> 情况是 O(n),正如您所观察到的,因此您的初始假设是不正确的。您可能会想到 平均 案例性能,这确实是 O(n log(n))。
  • @PatrickRoberts 在你引用的那一行中,我说的是 2 种特定算法,即合并排序和快速排序 [比较排序],其最佳情况复杂度实际上是 O(n log(n )) [正如我的算法书籍和快速谷歌搜索所引用的]。因此,我最初的假设是正确的,因为我实际上正在讨论比较排序算法及其最佳情况。
  • 您所做的所有陈述(直到最后一段)在技术上都是正确的(即使没有理由在各个地方使用 Omega 和 O - 这意味着您的误解)。但最后一段是不合逻辑的。在谈论什么缺陷?你能扩展一下吗?您对某些算法的最佳情况行为与最坏情况行为不同感到惊讶吗?您对可以修改算法以使其最佳情况的行为发生变化而不是最坏情况的行为感到惊讶吗?
  • “如果在这些排序算法中,我们首先在 O(n) 时间内遍历整个数组以确定数组是否已经排序” 那么你有一个不同的算法不同的最佳情况时间复杂度。
  • @MoB。我正在谈论的缺陷是,对于最佳情况复杂度超过 Ω(n) 的任何排序算法,可以对数组进行简单的 O(n) 遍历以确定数组是否已经排序。这将使所有此类排序算法的最佳情况复杂度为 Ω(n),从而使所有这些算法的最佳情况复杂度的概念变得多余,因为它将是 Ω(n),即对所有算法都相同。

标签: algorithm sorting time-complexity complexity-theory


【解决方案1】:

首先,您应该在脑海中区分案例(最佳、最差、平均等)和界限(上限、下限、O、Omega、Theta 等)

让我们专注于冒泡排序,定义如下:

if array == null or array.length < 2 then return
do
    swapped = false
    for i = 0 to array.length - 2
        if array[i] > array[i+1] then
            swap(array, i, i+1)
            swapped = true
until not swapped

该算法的最佳情况是排序数组,在​​这种情况下,下界 (Omega)、上界 (O) 和 Theta 都同意运行时由 f(n) = an 形式的函数绑定;也就是说,T(n) = O(n)。冒泡排序的最佳情况是线性的。

这个算法最坏的情况是一个反向排序的数组。在这种情况下,运行时间由像 g(n) = bn^2; 这样的函数从上到下限定。 T(n) = O(n^2) 在最坏的情况下。

您不会遗漏任何东西,算法具有不同的最坏情况和最佳情况运行时界限是完全正常的。算法也很可能不会针对最佳情况进行优化,因为最好的情况通常不是我们担心的情况;是的,归并排序可以首先检查数组是否已排序,但是在所有可能的长度为 N 的数组的集合中,这些数组的数量相对较少。

此外,您可以选择谈论最坏情况下的下限或最佳情况下的上限。这些东西不是我们通常关注的——而是关注最坏情况的上限,或者可能是最好情况的下限——但情况和界限是完全独立的东西,可以任意组合。

【讨论】:

  • 代码正下方段落的开头句真的很误导人。请考虑编辑它。
  • @MoB 不错,从最佳/最差到较低/较高进行了编辑。否则,应该没问题......当然也许我忽略了一些东西。
【解决方案2】:

使用渐近复杂度作为速度度量肯定存在问题。首先,显然常数很重要。 1000n 通常会比n log n 大得多,对于n 的任何实际值,n^1000 肯定比2^n 大得多。然而,事实证明,渐近复杂度通常是算法实际速度的一个相当好的指标。

你提出的问题也是正确的,但我不认为这是一个问题。确实,在快速排序开始时进行简单的isSorted() 检查会将其最佳案例复杂度降低到Θ(n),但很少有人关心最佳案例性能。事实上,许多常见问题的算法都可以修改为最佳情况线性,但这并不是很有用。

最后,请注意,这并不是渐近符号中的缺陷。进行随机猜测并验证猜测是否正确(例如通过猜测数组已经排序)通常确实可以提高最佳情况的性能,而对平均或最坏情况的影响很小,无论使用何种符号。

【讨论】:

  • 我同意你所说的大部分内容。关于您关于 NP 的句子:谈论 problem 的最佳(或最差或平均)情况(而不是 特定 解决问题的算法):对于每个 可计算的决策问题,存在一个算法以最佳情况复杂度 Θ(n) 解决它。您可能的意思是:NP 问题的每个(正确)解决方案都可以在多项式时间内得到验证,但这与最佳情况没有任何关系。
  • @MoB。我想我的意思是,对于 NP 中的每个问题,都有一个(非确定性)算法可以解决它,它在 any 实例的最佳情况下具有多项式运行时间的问题。我认为如果我们将 NP 中的问题替换为任何可计算的决策问题,并将多项式替换为线性,则此主张不再正确,但在这一点上我不确定。无论如何,我会编辑该部分,因为它不必要地令人困惑。
  • 删除“最好的情况”(或用“最坏的情况”替换它,但这是多余的),你就可以了。是的,NP 中不存在的 no 问题具有此属性。