如何在成对总和中找到第k个最大数,如setA + setB?

时间:2009-09-17 04:10:59

标签: algorithm

这里有两个整数集,比如A和B. 我们可以得到另一个集合C,其中每个元素都是A中元素a和B中元素b的总和。

例如,A = {1,2},B = {3,4},我们得到C = {4,5,6},其中4 = 1 + 3,5 = 1 + 4 = 2 + 3, 6 = 2 + 4

现在我想找出哪个数字是集合C中第k个最大的数字,例如5是上面例子中的第二大数字。

是否有有效的解决方案?

我知道成对求和排序是一个开放的问题,并且n ^ 2的时间界限较低。但由于只需要第k个最大数,我们可以从O(n)算法中学习未排序数组中的中位数。

感谢。

3 个答案:

答案 0 :(得分:4)

如果k非常接近1或N,任何懒惰地生成排序和的算法都可以直接运行,直到第k个或第N个项目弹出。

特别是,我正在考虑对以下空间进行最佳搜索:(a,b)表示来自A的第一个列表的项目,从B添加到b,第二个。

保持最佳=最低优先级队列对(a,b),成本(a,b)= A [a] + B [b]。

从优先级队列中的(1,1)开始,这是最小值。

Repeat until k items popped: 
 pop the top (a,b)
 if a<|A|, push (a+1,b)
 if a=1 and b<|B|, push (a,b+1)

这为您提供了锯齿梳连接,使您无需标记阵列中访问过的每个(a,b)。请注意,成本(a + 1,b)&gt; =成本(a,b)和成本(a,b + 1)&gt; =成本(a,b),因为A和B已排序。

这是一张梳子的图片,显示上面的后继生成规则(从左上角开始; a是水平方向):

|-------
|-------
|-------

这是(最多)所有| A | * | B |的最佳探索元组及其总和。

请注意,在弹出k之前推送的最多可能项目是2 * k,因为每个项目都有1或2个后继项。这是一个可能的队列状态,其中推入队列的项目标记为*

|--*----
|-*-----
*-------

*边界上方和左侧的所有内容都已弹出。

对于N-k<k情况,做同样的事情,但反向优先级队列顺序和探索顺序(或者,只是否定和反转值,得到(Nk)至少,然后否定并返回答案)

另请参阅:成对总和的排序列表on SOOpen problems project

答案 1 :(得分:4)

排序数组A&amp; B:O(mlogm + nlogn) 应用修改形式的算法合并2个排序数组:O(m + n) 即在每个点,你将这两个元素相加。 当你在C中得到(m + n-k + 1)个元素时,停止合并。该元素基本上是第k个。 例如。 {1,2}&amp; {3,4}:排序 C: {1 + 3,(1 + 4)|(2 + 3),2 + 4}

答案 2 :(得分:0)

嗯,O(n)将是一个下限(虽然可能不紧),否则你可以运行O(n)算法n次以获得O(n ^ 2)中的排序列表。

你能否假设这两组是排序的(你按照上面的排序顺序呈现)?如果是这样的话,你可能会得到一些平均情况,通过做一个“早出”,从最后一对元素开始,等等。但只是预感。