需要二次时间的算法任务?

时间:2012-12-16 06:54:45

标签: algorithm time-complexity

我知道冒泡排序,插入排序等,但有更有效的排序算法。通过Time Hierarchy Theorem,存在可以在O(n ^ 2)中解决但在O(n ^ r)中对于任何实数r<用于证明的结构不是很自然。什么是问题的一个很好的例子,其最有效的解决方案需要二次时间?

我正在寻找具有以下品质的东西:

  • 简单易懂
  • 经常使用的东西
  • 可以证明O(n ^ 2)是正确解决方案的最佳运行时间

小警告   - 输出不应该很大。 (如果你想要给定列表中每对整数的总和,显然需要二次时间来输出它们)。您可以假设它应该是decision problem,即具有是 - 否答案的{{3}}。我们还假设时间复杂度O(n ^ 2)是输入大小的函数,即n是表示输入所需的位数。

3 个答案:

答案 0 :(得分:8)

Matrix multiplication具有Ω的理论下界( n 2 ),因为所有 n 2 条目需要处理。迄今为止最着名的算法(根据上面链接的维基百科文章)具有复杂度O( n 2.3727 )。朴素算法具有复杂度 n 3

根据维基百科关于Computational complexity of mathematical operations的文章,三角矩阵的反向替换以获得 n 解是O( n 2 )。网上可能有很多其他的例子。

编辑:2014 paper by Michele Borassi, et al.,讨论了一些可以在O( n 2 中解决的决策问题(输出大小O(1)) )任何ε>时间但不在O( n 2- ε )中0.(当然,一如既往,这些结果取决于P≠NP,或者更准确地说,Strong Exponential Time Hypothesis是真的。)

他们的论文带有修改后的k-SAT problem

输入:

  • 两组变量 X = { x i }, Y = { y j }相同大小;
  • 这些变量的子句 C ,这样每个子句的最大大小为 k ;和
  • X Y 的两个电源组℘( X ),℘( Y )(使用过的)改变输入大小。)。

输出: true如果对所有满足所有子句的变量进行评估,则False

请注意,未修改的 k -SAT问题(输入中不包含上面的第三个项目符号)是NP完全的,因此通常会将其视为指数时间问题。但是,这里的输入大小本身就是变量数量的指数。他们表明,通过这种修改,问题总是可以在二次时间内解决(只需尝试所有可能的评估)。更重要的是,他们还表明这是解决问题的任何算法的最小时间复杂度。

有人可能反对这个修改过的 k -SAT问题很自然。然而,他们然后使用它来表明许多其他似乎很自然的问题也不能在O( n 2 )时间内解决。最简单的一个是子集图问题:

输入: X 的集合 X X 的子集 C

输出:图形 G =( C E ),其中,每个 C C '∈ C ,( C C ')∈ E 当且仅当 C C '。

答案 1 :(得分:1)

你在混合计算模型时犯了一个根本性的错误。

heirarchy定理是关于图灵机的时间,而其他大多数边界都有自己的模型(比如排序的比较模型),或者通常是关于RAM模型的。

所以真正的问题是,你在谈论哪种计算模型?

另外,谈论一个不比O(n ^ 2)(BigOh)差的最佳算法是无稽之谈。 BigOH是一个上限。你可能想要使用Theta。

答案 2 :(得分:1)

这差不多一年之后,但我想我有一个答案:部分订单发现。

考虑对总排序进行排序。你有一系列n个对象(我们假设它们是不同的),以及一个比较操作,它测试两个元素以查看一个是否小于或等于另一个。

您正在尝试发现元素所处的排列。有n个!可能的排列,所以你试图发现一个介于1和n之间的数字!每次比较都会给你一些信息。要发现1到n之间的数字!需要发现log(n!)位。因此,所需的比较次数也是log(n!)位,或:

log(n!)= n log n + o(n log n)=Ω(n log n)位

(所有对数当然都在基数2中。)

你不能比这更好。如果每个查询都提供了一位信息,并且您需要至少发现Ω(n log n)位,那么您需要进行Ω(n log n)次比较。如果你认为自己可以做得更好,可以选择Shannon,Chaitin和Kolmogorov。

但更好的是,即使在最坏的情况下(例如堆排序),也可以知道算法。从这个意义上说,堆排序是渐近最优的。

(注意,如果你有一个返回多个信息位的查询操作,你可以做得更好。例如,如果你能找到一个返回Ω(log n)位的那个,那么你应该能够在Ω(n)时间内排序。有关详细信息,请参阅基数排序。)

此分析适用于各种算法。在n个序列中查找单个事物需要发现1和n之间的数字,这意味着发现log n + O(1)位。如果查询操作返回一位,则需要Ω(log n)个查询来进行搜索。 (有关详细信息,请参阅二进制搜索。)

我想你可以看到我的目标。

现在假设你有n个元素,它们之间有一个部分顺序关系,但你不知道它是什么,想要找出来。但是,你所拥有的是一个查询,它比较两个元素x和y,如果x在部分顺序中小于或等于y,则返回“true”。

有一个明显的算法来发现需要Ω(n ^ 2)时间的偏序:简单地将每个元素与每个其他元素进行比较。

但这是最佳的吗?好吧,查询操作返回一位信息。 n个元素的部分订单数由Sloane's A001035给出。如果我正确读取它,此序列为Ω(2 ^(n ^ 2)),这意味着要发现部分顺序,您需要:

Ω(log 2 ^(n ^ 2))=Ω(n ^ 2)位

也就是说,你不能做得比Ω(n ^ 2)时间好,所以这是一个渐近最优的算法。

“那么”,我听到你问,“我买的是输入的大小是n的事实。但是不是输出的大小 O(n ^ 2),所以它在某种深层技术意义上实际上是一种线性算法?“

嗯......也许吧。我现在没有时间详细介绍细节,但我会回答一个问题。

在普通旧排序的情况下,我们可能会给出n 不同的元素。要区别对待,需要使用n 不同的标签进行标记。存储n个不同的标签意味着存储n个数字,每个数字在1和n之间。这些数字中的每一个都需要log n位来表示它,因此问题的总大小为n log n 。那么为什么我们不说堆排序在问题的大小上是线性的呢?