373. Find K Pairs with Smallest Sums
2016-07-24 15:04
501 查看
题目:找和最小的K对数字
You are given two integer arrays nums1 and nums2 sorted in ascending order and an integer k.
Define a pair (u,v) which consists of one element from the first array and one element from the second array.
Find the k pairs (u1,v1),(u2,v2)
...(uk,vk) with the
smallest sums.
Example 1:
Example 2:
Example 3:
题意:
给定两个按照递增排序好的整数数组nums1、nums2和一个整数k。
定义一个pair(u, v)对,其由一个元素来自于第一个数组,另一个元素来自于第二个数组组成。
找到k对pair(u1, v1),(u2, v2)... (uk, vk)和最小的数。
转载:[LeetCode]
Find K Pairs with Smallest Sums
思路一:
brute force的解法,这种方法我们从0循环到数组的个数和k之间的较小值,这样做的好处是如果k远小于数组个数时,我们不需要计算所有的数字对,而是最多计算k*k个数字对,然后将其都保存在res里,这时候我们给res排序,用我们自定义的比较器,就是和的比较,然后把比k多出的数字对删掉即可。
代码:C++版:528ms
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<min((int)nums1.size(), k); ++i) {
for (int j=0; j<min((int)nums2.size(), k); ++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) //将排序过后的集合中k对之后的对删掉
res.erase(res.begin()+k, res.end());
return res;
}
};
思路二:
使用multimap来做,思路是我们将数组对之和作为key存入multimap中,利用其自动排序的机制,这样我们就可以省去sort的步骤,最后把前k个存入res中即可。
代码:C++版:1070ms
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>> mul;
for (int i=0; i<min((int)nums1.size(), k); ++i) {
for (int j=0; j<min((int)nums2.size(), k); ++j) {
mul.insert({nums1[i] + nums2[j], {nums1[i], nums2[j]}});
}
}
for (auto it=mul.begin(); it!=mul.end(); ++it) {
res.push_back(it->second);
if (--k <= 0)
return res;
}
return res;
}
};
思路三:
使用priority_queue实现,也需要自定义比较器,整体思路和上面的没有什么区别。
代码:C++版:72ms
class Solution {
public:
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> q;
for (int i=0; i<min((int)nums1.size(), k); ++i) {
for (int j=0; j<min((int)nums2.size(), k); ++j) {
if (q.size() < k) {
q.push({nums1[i], nums2[j]});
} else if (nums1[i] + nums2[j] < q.top().first + q.top().second) {
q.push({nums1[i], nums2[j]});
q.pop();
}
}
}
while (!q.empty()) {
res.push_back(q.top());
q.pop();
}
return res;
}
struct cmp {
bool operator() (pair<int, int> &a, pair<int, int> &b) {
return a.first + a.second < b.first + b.second;
}
};
};
思路四:
下面这种方法比较另类,我们遍历nums1数组,对于nums1数组中的每一个数字,我们并不需要遍历nums2中所有的数字,实际上,对于nums1中的数字,我们只需要记录nums2中下一个可能组成数字对的坐标。
代码:C++版:44ms
class Solution {
public:
vector<pair<int, int>> kSmallestPairs(vector<int>& nums1, vector<int>& nums2, int k) {
vector<pair<int, int>> res;
int size = min(k, int(nums1.size() * nums2.size()));
vector<int> idx(nums1.size(), 0);
for (int i=0; i<size; ++i) {
int t = 0, sum = INT_MAX;
for (int j=0; j<nums1.size(); ++j) {
if (idx[j]<nums2.size() && sum>=nums1[j]+nums2[idx[j]]) {
t = j;
sum = nums1[j] + nums2[idx[j]];
}
}
res.push_back({nums1[t], nums2[idx[t]]});
++idx[t];
}
return res;
}
};
思路五:转载地址:https://discuss.leetcode.com/topic/50481/clean-16ms-c-o-n-space-o-klogn-time-solution-using-priority-queue
使用堆辅助实现。
代码:C++版:16ms
class Solution {
public:
vector<pair<int, int>> kSmallestPairs(vector<int>& nums1, vector<int>& nums2, int k) {
vector<pair<int,int>> result;
if (nums1.empty() || nums2.empty() || k <= 0)
return result;
auto comp = [&nums1, &nums2](pair<int, int> a, pair<int, int> b) {
return nums1[a.first] + nums2[a.second] > nums1[b.first] + nums2[b.second];}; //自定义比较器
priority_queue<pair<int, int>, vector<pair<int, int>>, decltype(comp)> min_heap(comp);
min_heap.emplace(0, 0);
while(k-- > 0 && min_heap.size())
{
auto idx_pair = min_heap.top(); min_heap.pop();
result.emplace_back(nums1[idx_pair.first], nums2[idx_pair.second]);
if (idx_pair.first + 1 < nums1.size())
min_heap.emplace(idx_pair.first + 1, idx_pair.second);
if (idx_pair.first == 0 && idx_pair.second + 1 < nums2.size())
min_heap.emplace(idx_pair.first, idx_pair.second + 1);
}
return result;
}
};
You are given two integer arrays nums1 and nums2 sorted in ascending order and an integer k.
Define a pair (u,v) which consists of one element from the first array and one element from the second array.
Find the k pairs (u1,v1),(u2,v2)
...(uk,vk) with the
smallest sums.
Example 1:
Given nums1 = [1,7,11], nums2 = [2,4,6], k = 3 Return: [1,2],[1,4],[1,6] The first 3 pairs are returned from the sequence: [1,2],[1,4],[1,6],[7,2],[7,4],[11,2],[7,6],[11,4],[11,6]
Example 2:
Given nums1 = [1,1,2], nums2 = [1,2,3], k = 2 Return: [1,1],[1,1] The first 2 pairs are returned from the sequence: [1,1],[1,1],[1,2],[2,1],[1,2],[2,2],[1,3],[1,3],[2,3]
Example 3:
Given nums1 = [1,2], nums2 = [3], k = 3 Return: [1,3],[2,3] All possible pairs are returned from the sequence: [1,3],[2,3]
题意:
给定两个按照递增排序好的整数数组nums1、nums2和一个整数k。
定义一个pair(u, v)对,其由一个元素来自于第一个数组,另一个元素来自于第二个数组组成。
找到k对pair(u1, v1),(u2, v2)... (uk, vk)和最小的数。
转载:[LeetCode]
Find K Pairs with Smallest Sums
思路一:
brute force的解法,这种方法我们从0循环到数组的个数和k之间的较小值,这样做的好处是如果k远小于数组个数时,我们不需要计算所有的数字对,而是最多计算k*k个数字对,然后将其都保存在res里,这时候我们给res排序,用我们自定义的比较器,就是和的比较,然后把比k多出的数字对删掉即可。
代码:C++版:528ms
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<min((int)nums1.size(), k); ++i) {
for (int j=0; j<min((int)nums2.size(), k); ++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) //将排序过后的集合中k对之后的对删掉
res.erase(res.begin()+k, res.end());
return res;
}
};
思路二:
使用multimap来做,思路是我们将数组对之和作为key存入multimap中,利用其自动排序的机制,这样我们就可以省去sort的步骤,最后把前k个存入res中即可。
代码:C++版:1070ms
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>> mul;
for (int i=0; i<min((int)nums1.size(), k); ++i) {
for (int j=0; j<min((int)nums2.size(), k); ++j) {
mul.insert({nums1[i] + nums2[j], {nums1[i], nums2[j]}});
}
}
for (auto it=mul.begin(); it!=mul.end(); ++it) {
res.push_back(it->second);
if (--k <= 0)
return res;
}
return res;
}
};
思路三:
使用priority_queue实现,也需要自定义比较器,整体思路和上面的没有什么区别。
代码:C++版:72ms
class Solution {
public:
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> q;
for (int i=0; i<min((int)nums1.size(), k); ++i) {
for (int j=0; j<min((int)nums2.size(), k); ++j) {
if (q.size() < k) {
q.push({nums1[i], nums2[j]});
} else if (nums1[i] + nums2[j] < q.top().first + q.top().second) {
q.push({nums1[i], nums2[j]});
q.pop();
}
}
}
while (!q.empty()) {
res.push_back(q.top());
q.pop();
}
return res;
}
struct cmp {
bool operator() (pair<int, int> &a, pair<int, int> &b) {
return a.first + a.second < b.first + b.second;
}
};
};
思路四:
下面这种方法比较另类,我们遍历nums1数组,对于nums1数组中的每一个数字,我们并不需要遍历nums2中所有的数字,实际上,对于nums1中的数字,我们只需要记录nums2中下一个可能组成数字对的坐标。
代码:C++版:44ms
class Solution {
public:
vector<pair<int, int>> kSmallestPairs(vector<int>& nums1, vector<int>& nums2, int k) {
vector<pair<int, int>> res;
int size = min(k, int(nums1.size() * nums2.size()));
vector<int> idx(nums1.size(), 0);
for (int i=0; i<size; ++i) {
int t = 0, sum = INT_MAX;
for (int j=0; j<nums1.size(); ++j) {
if (idx[j]<nums2.size() && sum>=nums1[j]+nums2[idx[j]]) {
t = j;
sum = nums1[j] + nums2[idx[j]];
}
}
res.push_back({nums1[t], nums2[idx[t]]});
++idx[t];
}
return res;
}
};
思路五:转载地址:https://discuss.leetcode.com/topic/50481/clean-16ms-c-o-n-space-o-klogn-time-solution-using-priority-queue
使用堆辅助实现。
代码:C++版:16ms
class Solution {
public:
vector<pair<int, int>> kSmallestPairs(vector<int>& nums1, vector<int>& nums2, int k) {
vector<pair<int,int>> result;
if (nums1.empty() || nums2.empty() || k <= 0)
return result;
auto comp = [&nums1, &nums2](pair<int, int> a, pair<int, int> b) {
return nums1[a.first] + nums2[a.second] > nums1[b.first] + nums2[b.second];}; //自定义比较器
priority_queue<pair<int, int>, vector<pair<int, int>>, decltype(comp)> min_heap(comp);
min_heap.emplace(0, 0);
while(k-- > 0 && min_heap.size())
{
auto idx_pair = min_heap.top(); min_heap.pop();
result.emplace_back(nums1[idx_pair.first], nums2[idx_pair.second]);
if (idx_pair.first + 1 < nums1.size())
min_heap.emplace(idx_pair.first + 1, idx_pair.second);
if (idx_pair.first == 0 && idx_pair.second + 1 < nums2.size())
min_heap.emplace(idx_pair.first, idx_pair.second + 1);
}
return result;
}
};
相关文章推荐
- UVA11374_Airport Express
- CodeForces 474C - Captain Marmot
- viterbi,维特比算法通俗理解
- ServletContainerInitializer初始化器
- ServletContainerInitializer初始化器
- 2016 Multi-University Training Contest 1 1001 Abandoned country
- HDU 5735 Born Slippy ( from:2016 Multi-University Training Contest 2 )
- 服务大众的人工智能---认知服务
- gdb调试core时能用i locals看栈变量、函数行(即不出现No symbol table info available)的必要条件: 1. 编译时有-g参数; 2.so库未被strip脱衣服
- bio nio aio
- 关于inputStream.available()方法获取下载文件的总大小
- 最容易读进去的深度学习科普贴
- LeetCode 172. Factorial Trailing Zeroes
- gipchaInternalResolve:failed to resolve ret gipcretKeyNotFound(36),
- 刨一刨内核container_of()的设计精髓
- MapReduce Main Points
- AC again
- 2016 Multi-University Training Contest 2 H Helter Skelter (hdu5741) 【二分】
- HDU-1848 Fibonacci again and again(组合游戏)
- 1079. Total Sales of Supply Chain (25)