给定具有N个元素的数组A,我需要找到对(i,j),使得i不等于j并且如果我们为所有对(i,i)写出和A [i] + A [j] j)然后它出现在第k位。
示例:设N = 4,数组A = [1 2 3 4],如果K = 3,则答案为5,因为我们可以清楚地看到sum数组变为这样:[3 ,4,5,5,6,7]
我不能去所有的i和j,因为N可以达到100000.请帮助解决这个问题
我的意思是这样的:
int len=N*(N+1)/2;
int sum[len];
int count=0;
for(int i=0;i<N;i++){
for(int j=i+1;j<N;j++){
sum[count]=A[i]+A[j];
count++;
}
}
//Then just find kth element.
我们不能采用这种方法
答案 0 :(得分:0)
我假设你从http://www.careercup.com/question?id=7457663得到了这个问题。
如果k
接近0
,则How to find kth largest number in pairwise sums like setA + setB?的已接受答案可以很容易地适应此问题并且非常有效。您需要O(n log(n))
对数组进行排序,O(n)
以设置优先级队列,然后O(k log(k))
来迭代元素。如果k
接近n*n - n
,反向解决方案也会有效。
如果k
接近n*n/2
那么那就不会很好。但是你可以调整http://en.wikipedia.org/wiki/Quickselect的支点方法来解决这个问题。首先是O(n log(n))
,您可以对数组进行排序。在时间O(n)
中,您可以设置表示各个连续列范围的数据结构。然后,您需要选择O(log(n))
次枢轴。 (请记住,log(n*n) = O(log(n))
。)对于每个数据透视表,您可以对每列进行二进制搜索,以确定每列的分割位置O(log(n))
,以及O(n log(n))
的总成本所有专栏。
生成的算法为O(n log(n) log(n))
。
更新:我没时间做手指提供代码。但我可以概述一些实现中可能具有的类。
实现有点冗长,但有时这是一个很好的通用算法的成本。
ArrayRangeWithAddend
。这表示一个数组的范围,总和为一个值。具有array
(引用或指针,因此基础数据可以在对象之间共享),start
和end
到范围,以及要添加到范围中每个元素的值的shiftValue
。
它应该有一个构造函数。给出size
的方法。一种方法partition(n)
将其调整到小于n
的范围,计数等于n
,范围大于n
。并value(i)
提供i
&#39;值。
ArrayRangeCollection
。这是ArrayRangeWithAddend
个对象的集合。它应该有方法来给出它的大小,选择一个random
元素,并将partition(n)
方法添加到ArrayRangeCollection
n
以下n
,等于{ {1}}以及大于ArrayRangeCollection
的{{1}}。在n
方法中,最好不要包含大小为partition
的{{1}}个对象。
现在您的主程序可以对数组进行排序,并创建一个涵盖您感兴趣的所有总和的ArrayRangeWithAddend
。然后可以使用0
和ArrayRangeCollection
方法来实现标准的quickselect算法,你可以在我提供的链接中找到。
答案 1 :(得分:0)
基于K <= 50
的事实的解决方案:让我们按排序顺序获取数组的第一个K + 1
元素。现在我们可以尝试他们所有的组合。正确性证明:我们假设一对(i, j)
是答案,j > K + 1
。但是K
对具有相同或更小的总和:(1, 2), (1, 3), ..., (1, K + 1)
。因此,它不能是K
对。
通过使用quickselect算法选择O(N + K ^ 2)
最小数字,可以实现K + 1
时间复杂度(可能做得更好,但不是必需的)。您也可以只使用数组并获得O(N * log N + K ^ 2 * log K)
复杂度。
答案 2 :(得分:0)
以下是如何做到这一点(伪代码)。我现在已经确认它可以正常工作。
//A is the original array, such as A=[1,2,3,4]
//k (an integer) is the element in the 'sum' array to find
N = A.length
//first we find i
i = -1
nl = N
k2 = k
while (k2 >= 0) {
i++
nl--
k2 -= nl
}
//then we find j
j = k2 + nl + i + 1
//now compute the sum at index position k
kSum = A[i] + A[j]
编辑:
我现在测试了这个作品。我必须修复一些部分......基本上k
输入参数应该使用基于0的索引。 (OP似乎使用基于1的索引。)
编辑2:
我会试着解释一下我的理论。我开始的概念是sum
数组应该可视化为2D锯齿状数组(宽度随着高度的增加而减小),坐标(如OP中所述)为i
和{{ 1}}。因此,对于像[1,2,3,4,5]这样的数组,j
数组将被设想为:
sum
顶行是3,4,5,6,
5,6,7,
7,8,
9.
等于0的所有值。第二行是i
等于1的位置。要找到'j'的值,我们会在列方向上执行相同的操作。
...对不起我无法解释这个更好!