渐近下界不起作用为什么?

问题描述

好吧,这显然不是一个家庭作业问题,但这是事实: 气泡排序算法被称为O(n ^ 2),Ω(n)。 但是,如果将其时间复杂度绘制为图表(平均情况),并尝试对其进行下限限制,则更精确的下限将为Ω(n ^ 2)。但是从上下文来看,我们看到Ω(n)是正确的。那么为什么下限算法的运行时间不起作用?

解决方法

根据定义,

Ω(n)为下限,不必太紧。它只是保证算法不会比线性算法更好。

Ω(1),Ω(log(n))也是冒泡排序执行时间的有效下限。信息不多,但仍然有效。

,

我认为您正在混淆一些概念:

  1. 下限与上限:Ω(f(n))是一个下限,O(f(n))是一个上限。

  2. 最佳与最坏情况:除非另有说明,否则Ω(f(n))和O(f(n))均指最坏情况下的运行时间,取决于输入大小。

对于冒泡排序,大小为n的最坏案例输入被保证需花费二次时间,因此冒泡排序为O(n 2 )和Ω(n 2 )。

“气泡排序据说是Ω(n)”的原因是很多人都把它弄乱了。

请记住,Ω(f(n))是在f(n)下渐近界定的函数的 set ,当您看到“算法X为Ω(f(n))时, ,将其读为“算法X 的最坏情况运行时间在Ω(f(n))中。”

(但是请注意,德米特里的答案也是正确的。因为ω是一个下限,所以Ω(1),Ω(log n),Ω(n),Ω(n log n)和Ω(n 2 )全部适用)

,

以下陈述都是正确的:

  • 对于每个数字n,冒泡排序在长度为n的列表上执行的比较不超过n(n-1)/ 2个比较和n(n-1)/ 2个交换
  • 对于每个数字n,都有一个长度为n的列表,在该列表上,冒泡排序正好执行n(n-1)/ 2个比较和n(n-1)/ 2个交换(示例:以相反顺序排序的列表)
  • 对于每个数字n,Bubble排序对长度为n的列表进行的比较绝不会少于(n-1)次。
  • 对于每个数字n,都有一个长度为n的列表,气泡排序将在该列表上进行正好(n-1)个比较和0次交换(例如:排序列表)
  • 对于每个数字n,如果我们采用列表[1,2,...,n]并随机对其进行随机洗净,则冒泡排序的预期交换次数为n(n-1)/ 4(说明:this answer on CS.stackexchange

结论:如果我们忘记了乘法常数,则最差情况下的运行时间为n ^ 2,气泡排序的最佳情况下的运行时间为n,平均运行时间为n ^ 2。

请注意,“平均运行时间”总是有点模棱两可。为了消除歧义,我在最后一点指出了不同的观点。如果您的随机列表遵循不同的概率分布,那么您将获得不同的结果。特别是,在具有大量重复元素的列表上,冒泡排序将需要较少的交换(也许也不需要进行比较)。但是,如果您不关心确切的乘法常数,那么生成“随机列表”的大多数“合理”方法将导致预期的n ^ 2复杂度。

现在,您的问题可能变为:为什么气泡排序的预期运行时间如此接近其最坏情况下的运行时间,而又远离其最佳情况下的运行时间?

这个问题的答案是:绝大多数排列被“合理地改组”,只有很少一部分排列被“几乎排序”。换句话说,如果您随机地随机排列列表,那么结果将是“随机的”。如果随机播放一副纸牌,则不小心对纸牌进行排序的可能性非常低。

这个问题也具有欺骗性:最坏情况下的比较数是n ^ 2/2;预期的比较次数为n ^ 2/4;比较的最佳情况是n-1。因此,实际上,预期的比较次数几乎是最坏情况和最好情况之间的一半

关于CS.stackexchange的答案也是一个很好的解释:在列表中的所有成对元素中,我们期望一半成对的相对顺序,一半成对的相反顺序。因此,预期的运行时间恰好是最坏情况下运行时间的一半。

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...