题目
有两个序列A和B,A=(a1,a2,…,ak),B=(b1,b2,…,bk),A和B都按升序排列。对于1<=i,j<=k,求k个最小的(ai+bj)。要求算法尽量高效。
分析
我们可以使用快速排序或堆排序将相加后的数组进行排序,然后取出最小的k个数即可,但是这样的话,题目中有一个条件没有用到,那就是序列A和序列B都是有序的。如果用上这个条件是不是有更高效的方法呢?
由于序列A和B都是按升序排列,那么假设ai + bj <= C, 那么任意的0 <= p < i and 0 <= q < j,都会有ap + bq <= ai + bj, 因此我们若想找到k个最小的(ai+bj),只需要找到使得(i-1) * j < k或者(j-1) * i < k,当然获得的是其中最小的一个值的情况下的i与j的取值,获取到i与j的值过后,那么p与q的取值相加就是最小的k个和。
代码如下:
#include<iostream>
using namespace std;
int A[] = {3, 9, 12, 20, 23, 34, 39};
int B[] = {1, 10, 15, 19, 25, 39, 47};
int k = sizeof(A)/sizeof(A[0]);
int p, q;
int *KMinSelect(int *a, int *b, int k){
int i = k, j = k;
int count = 0;
int *temp = new int[k];
while(i>0 && j>0){
if(a[i-1] > b[j-1]){
if((i-1)*j >= k){
i--;
} else {
break;
}
} else {
if((j-1)*i >= k){
j--;
} else{
break;
}
}
}
if(a[i-1] > b[j-1]){
for(int p=0; p<i; p++)
for(int q=0; q<j; q++)
if(count < k)
temp[count++] = a[p] + b[q];
} else {
for(int q=0; q<j; q++)
for(int p=0; p<i; p++)
if(count < k)
temp[count++] = a[p] + b[q];
}
return temp;
}
int main(){
int *result = KMinSelect(A, B, k);
for(int i=0; i<k; i++)
cout << *(result+i) << " ";
cout << endl;
return 0;
}
这篇博客探讨了如何高效地解决一个数学问题:给定两个升序排列的序列A和B,找出它们对应元素相加后的k个最小和。通过分析有序序列的性质,提出利用有序性避免排序,直接找到i与j的取值来得到最小k个数之和,从而提高算法效率。

1840

被折叠的 条评论
为什么被折叠?



