您的位置:首页 > 编程语言 > C语言/C++

求两个有序数组两两相加的值最小的K个数

2016-08-06 13:29 197 查看
题目描述:

有两个大小分别是lenA和lenB的数组A,B,它们元素的按非递减有序排列,找出这样的k个最小的(ai + bj) ,其中 0<= i < lenA,0<= j < lenB,要求算法的时间复杂度和空间复杂度尽量低。

例如对于:

A = 1,2,3,4

B = 2,3,4,5

ai+bj的所有组合有4*4 = 16个,如下图:

b\a 1   2   3   4

2   3   4   5   6

3   4   5   6   7

4   5   6   7   8

5   6   7   8   9

依次排序为:3,4,4,5, 5,5,6,6, 6,6,7,7, 7,8,8,9 (共16个)

解题思路:

最小堆方法实现的代码,其思路如下:

首先把a0+b0的结果放入堆中,此时堆中只有一个元素,自然满足最小堆条件,然后开始出堆的操作,从堆里面取出根节点(也就是最小的值),例如是a[i]+b[j],则需要像最小堆中压入a[i+1]b[j] 和 a[i]+b[j+1],当然,要保证下标不越界,如果下标越界了则忽略,另外要保证已经压入过堆中的组合(即使已经从堆中被取出了的)不再被压入堆中。不段进行出堆、入堆的操作,重复K次,就得到了K个最小的组合值。

堆的最大深度为logK,所以时间复杂度为K*logK数量级。

实现代码如下:

#include <iostream>
#include <vector>
#include <algorithm>
#include <map>
using namespace std;

struct Node{
int posA;
int posB;
int sum;
Node(){}
Node(int a, int b, int s) :posA(a), posB(b), sum(s){}
};

class Solution{
public:
static bool cmp(const Node& node1, const Node& node2)
{
return node1.sum > node2.sum;
}
vector<int> topKOfTwoSortedArray(const vector<int>& A, const vector<int>& B, int k)
{
vector<int> ans;
if ((A.size() == 0 && B.size() == 0) || k<=0) return ans;
int nA = A.size();
int nB = B.size();
if (k > nA*nB) k = nA*nB;
map<pair<int,int>, bool> stats;
vector<Node> heapAux;
heapAux.push_back(Node(0,0,A[0]+B[0]));
stats[make_pair(0,0)] = true;
make_heap(heapAux.begin(), heapAux.end(), cmp);
while (k>0){
pop_heap(heapAux.begin(), heapAux.end(), cmp);
Node tmp = heapAux.back();
heapAux.pop_back();
ans.push_back(tmp.sum);
--k;
int idxA = tmp.posA;
int idxB = tmp.posB;
if (idxA + 1 < nA && !stats[make_pair(idxA + 1, idxB)]){
stats[make_pair(idxA + 1, idxB)] = true;
heapAux.push_back(Node(idxA + 1, idxB, A[idxA + 1] + B[idxB]));
push_heap(heapAux.begin(), heapAux.end(), cmp);
}
if (idxB + 1 < nB && !stats[make_pair(idxA, idxB + 1)]){
stats[make_pair(idxA, idxB + 1)] = true;
heapAux.push_back(Node(idxA, idxB + 1, A[idxA] + B[idxB + 1]));
push_heap(heapAux.begin(), heapAux.end(), cmp);
}
}
return ans;
}
};

int main()
{
vector<int> A = {1,2,3,4};
vector<int> B = {2,3,4,5};
int k = 12;
Solution sln;
vector<int> ans = sln.topKOfTwoSortedArray(A, B, k);
for (int i = 0; i < k; ++i){
cout << ans[i] << " ";
}
cout << endl;
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  面试题 数组 C++
相关文章推荐