渐近符号有缺陷吗?

问题描述

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

正如我们所知,在渐近符号中 -

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

还有,

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

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

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

解决方法

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

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

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

,

首先,您应该在头脑中区分情况(最佳、最差、平均等)和界限(上限、下限、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 的所有可能数组的集合中,这些数组的数量相对较少。

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