“查找总和小于某个数字的所有三元组”是否有比O(n3)运行时更好的解决方案?

时间:2014-09-04 16:22:44

标签: arrays algorithm

我在接受采访时被问到这个问题。

“给定一系列整数,找到总和小于某个数字的所有三胞胎”

经过一番争吵之后,我告诉采访者,最好的解决方案仍然会导致最坏情况的运行时间O(n 3 )并且可能需要O(n 3

面试官公然不同意我并告诉我“你需要回到你的算法......”。

我错过了什么吗?

4 个答案:

答案 0 :(得分:3)

可能的优化将是:

  1. 删除数组中大于sum;
  2. 的所有元素
  3. 对数组进行排序;
  4. 运行O(N^2)以获取a[i] + a[j],然后在sum - a[i] - a[j]范围内对[j + 1, N]进行二分搜索,索引是可能的候选人数,但您应该减去j因为他们已被保险。
  5. 复杂性将为O(N^2 log N),稍好一些。

答案 1 :(得分:2)

您可以解决此O(n^2)时间:

  • 首先,对数组进行排序。
  • 然后,使用第一个指针i循环遍历数组。
  • 现在,使用第二个指针j从那里循环,第三个指针k同时循环结束。
  • 当您处于A[i]+A[j]+A[k] < X的情况时,您知道所有j<k'<k同样适用,因此请使用k-j增加您的计数并增加j。我保留A[i]+A[j]+A[k+1] >= X隐藏的不变量,因此递增j只会使该语句更强。
  • 否则,递减k。当jk见面时,请增加i
  • 您只会增加j并递减k,因此需要O(n)摊销时间才能见面。

在伪代码中:

count= 0
for i = 0; i < N; i++
    j = i+1
    k = N-1
    while j < k
        if A[i] + A[j] + A[k] < X
            count += k-j
            j++
        else
            k--

我看到你要求所有三胞胎。很明显,可以有O(n^3)三胞胎,所以如果你想要它们,你将需要尽可能多的时间,最糟糕的情况。

答案 2 :(得分:0)

O(n ^ 2)算法。

对列表进行排序。

对于每个元素ai,这是计算组合数的方式:

二进制搜索并找到最大aj,使得j <1。我和ai + aj&lt; =总数。

二进制搜索并找到最大ak,使得k <1。 j和ai + aj + ak&lt; = total

对于(ai,aj)的这种特定组合,k是小于或等于总数的和的数量。

现在递减j并尽可能地增加k(但是ai + aj + ak <=总数)

增量和减量的总数小于i。因此,对于特定的i,复杂性是O(i)。因此总体复杂度为O(n ^ 2)。

我遗漏了许多角落条件,但这应该会给你一个想法。

=== EDIT ===

在最坏的情况下,有O(n ^ 3)个解决方案。因此明确输出它们肯定需要O(n ^ 3)时间。没有办法解决它。

但是如果你想返回一个隐式列表(即一个压缩的组合列表),这仍然有用。压缩输出的一个例子是(ai,aj,ak),其中k为1:p。

答案 3 :(得分:0)

这是输出大小很重要的问题的示例。例如,如果数组仅包含1, 2, 3, 4, 5, ..., n且最大值设置为3n,那么每个三元组都将是一个答案,而您必须执行{{1}工作只是为了列出所有。另一方面,如果最大值为Ω(n^3),那么在确认所有项目都太大后,在0时间内完成会很不错。

基本上,我们希望output-sensitive algorithm的运行时间类似于O(n),其中O(f(n) + t)是输出大小,t是输入大小。

n算法基本上可以跟踪三元组从超过限制转变到限制之下的转换点。然后它会产生该表面下的所有东西。空间是三维的,因此表面是二维的,你可以在一个恒定的时间内从一点到另一点跟踪它。

这里有一些python代码(未经测试!):

O(n^2 + t)