我在接受采访时被问到这个问题。
“给定一系列整数,找到总和小于某个数字的所有三胞胎”
经过一番争吵之后,我告诉采访者,最好的解决方案仍然会导致最坏情况的运行时间O(n 3 )并且可能需要O(n 3 )
面试官公然不同意我并告诉我“你需要回到你的算法......”。
我错过了什么吗?
答案 0 :(得分:3)
可能的优化将是:
sum
; O(N^2)
以获取a[i] + a[j]
,然后在sum - a[i] - a[j]
范围内对[j + 1, N]
进行二分搜索,索引是可能的候选人数,但您应该减去j
因为他们已被保险。复杂性将为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
。当j
和k
见面时,请增加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)