给定两个以升序排列的整形数组 nums1 和 nums2, 以及一个整数 k。
定义一对值 (u,v),其中第一个元素来自 nums1,第二个元素来自 nums2。
找到和最小的 k 对数字 (u1,v1), (u2,v2) ... (uk,vk)。
示例 1:
给出: nums1 = [1,7,11], nums2 = [2,4,6], k = 3 返回: [1,2],[1,4],[1,6] 返回序列中的前 3 对数: [1,2],[1,4],[1,6],[7,2],[7,4],[11,2],[7,6],[11,4],[11,6]
示例 2:
给出:nums1 = [1,1,2], nums2 = [1,2,3], k = 2 返回: [1,1],[1,1] 返回序列中的前 2 对数: [1,1],[1,1],[1,2],[2,1],[1,2],[2,2],[1,3],[1,3],[2,3]
示例 3:
给出:nums1 = [1,2], nums2 = [3], k = 3 返回: [1,3],[2,3] 也可能序列中所有的数对都被返回: [1,3],[2,3]
思路一:直接创建vector<int,int> res的变量,遍历nums1和nums2的所有组合,只不过在vector内部的排序算法改成自定义的根据和进行排序的算法。
参考代码:
class Solution {
public:
vector<pair<int, int>> kSmallestPairs(vector<int>& nums1, vector<int>& nums2, int k) {
vector<pair<int, int>> res;
for (int i = 0; i < nums1.size(); i++) {
for (int j = 0; j < nums2.size(); j++) {
res.push_back({nums1[i],nums2[j]});
}
}
sort(res.begin(), res.end(), [](pair<int, int>& a, pair<int, int>& b) {return a.first + a.second < b.first + b.second;});
if (res.size() > k) res.erase(res.begin() + k, res.end());
return res;
}
};
思路二:使用multimap(键可重复),其排序也是自定义算法,最后放到res中。
参考代码:
class Solution {
public:
vector<pair<int, int>> kSmallestPairs(vector<int>& nums1, vector<int>& nums2, int k) {
vector<pair<int, int>> res;
multimap<int, pair<int, int>> m;
for (int i = 0; i < nums1.size(); i++) {
for (int j = 0; j < nums2.size(); j++) {
m.insert({ nums1[i] + nums2[j],{nums1[i],nums2[j]} });
}
}
for (auto it = m.begin(); it != m.end(); it++) {
res.push_back(it->second);
if (--k <= 0) return res;
}
return res;
}
};
思路三:本来前两种算法就够了,主要是看到提交的时间实在是令人捉急,并且这道题的tag是堆,目前还没有用到堆呢,对于用堆来解题思路和上面一样,不过这里要想清楚是用最大堆还是最小堆,直觉既然是找最小的值,那么肯定是最小堆了。用最小堆也可以解,我们来看如何用最大堆来解题,我们保证堆里的元素只有k个且堆顶是最大值,那么如果有一个较小的组合进来了,就压入小组合,弹出堆顶元素(这时最大的值被弹出了,剩下的都是较小的,以此类推可以得到最小的k个组合),但是要注意这时堆顶的元素依然是最小的k个组合的最大的组合。
参考代码:
class Solution {
public:
struct cmp {
bool operator ()(pair<int, int> &a, pair<int, int> &b) {
return (a.first + a.second) < (b.first + b.second);
}
};
vector<pair<int, int>> kSmallestPairs(vector<int>& nums1, vector<int>& nums2, int k) {
vector<pair<int, int>> res;
priority_queue<pair<int, int>, vector<pair<int, int>>, cmp> heap;
for (int i = 0; i < nums1.size(); i++) {
for (int j = 0; j < nums2.size(); j++) {
if (heap.size() < k) heap.push({ nums1[i],nums2[j] });
else {
if ((nums1[i] + nums2[j]) < (heap.top().first + heap.top().second)) {
heap.push({ nums1[i],nums2[j] });
heap.pop();
}
}
}
}
while (!heap.empty()) {
res.push_back(heap.top()); heap.pop();
}
return res;
}
};