有序矩阵中的第 k 个最小数组和
主要内容:
373. 查找和最小的 K 对数字
题目描述
给定两个以 升序排列 的整数数组 nums1 和 nums2 , 以及一个整数 k 。 定义一对值 (u,v),其中第一个元素来自 nums1,第二个元素来自 nums2 。 请找到和最小的 k 个数对 (u1,v1), (u2,v2) ... (uk,vk) 。
示例
输入: 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]
直接先上代码
- 优先队列——自定义比较函数
解题思路可参考Leetcode,这里不赘述,主要给出priority_queue的自定义比较函数的方式
知识点列表:
- decltype: 可推断变量或者函数类型。
- std::initializer_list:是C++11引入的一种特殊类型,用于方便地初始化容器和其他对象。它提供了一种简洁的语法,可以在对象的构造函数中使用花括号 {} 来初始化一组值
- 优先队列的emplace操作:
原地构造的方式插入一个元素到优先队列中,而不是通过复制或移动现有对象。它接受参数作为构造函数的参数,并使用这些参数在优先队列中创建新的元素。
参考资料
vector<vector<int>> kSmallestPairs(vector<int>& nums1, vector<int>& nums2, int k) {
// 使用lambda表达式定义比较函数
auto cmp = [&](const pair<int, int> &p1, const pair<int, int> &p2){
return nums1[p1.first] + nums2[p1.second] > nums1[p2.first] + nums2[p2.second];
};
// 优先队列的元素为pair<int, int>,存储元素的容器为vector, 自定义的比较函数为cmp
priority_queue<pair<int, int>, vector<pair<int, int>>, decltype(cmp)> pq(cmp);
for(int idx = 0; idx < nums2.size(); ++idx){
pq.emplace(0, idx);
}
vector<vector<int>> ans;
while(pq.size() && k){
auto top = pq.top(); pq.pop();
// initializer_list<int> 方便地初始化容器和其他对象
ans.push_back(initializer_list<int>{nums1[top.first], nums2[top.second]});
if(top.first + 1 < nums1.size()){
pq.emplace(top.first + 1, top.second);
}
--k;
}
return ans;
}
优先队列——自定义元素以及元素的比较
自定义元素,并且定义元素的类中自定义比较函数
// 元素类,且重载<运算符来实现元素大小的比较
class Entry{
public:
size_t i, j;
int s;
Entry(size_t _i, size_t _j, int _s):i(_i), j(_j), s(_s){
}
bool operator <(const Entry& e) const{
return s > e.s;
}
};
vector<vector<int>> kSmallestPairs(vector<int>& nums1, vector<int>& nums2, int k) {
priority_queue<Entry> pq;
for(int idx = 0; idx < nums2.size(); ++idx){
pq.emplace(0, idx, nums1[0] + nums2[idx]);
}
vector<vector<int>> ans;
while(pq.size() && k){
auto entry = pq.top(); pq.pop();
ans.push_back(initializer_list<int>{nums1[entry.i], nums2[entry.j]});
if(entry.i + 1 < nums1.size()){
// 当优先队列中存储的元素定义了构造函数,那么可以使用emplace来添加元素到优先队列。
pq.emplace(entry.i + 1, entry.j, nums1[entry.i + 1] + nums2[entry.j]);
}
--k;
}
return ans;
}
重载()运算符的优先队列方式
自定义比较的类(结构体),其输入为两个元素,也即优先队列实际存储的元素。
- tuple的使用方法:获取元素使用get操作。
struct cmp{
bool operator()(const tuple<int,int,int> &t1, const tuple<int,int,int> &t2){
return get<2>(t1) > get<2>(t2);
}
};
vector<vector<int>> kSmallestPairs(vector<int>& nums1, vector<int>& nums2, int k) {
priority_queue<tuple<int, int, int>, vector<tuple<int, int, int>>, cmp> pq;
for(int idx = 0; idx < nums2.size(); ++idx){
pq.emplace(0, idx, nums1[0] + nums2[idx]);
}
vector<vector<int>> ans;
while(pq.size() && k){
auto top = pq.top(); pq.pop();
ans.push_back(initializer_list<int>{nums1[get<0>(top)], nums2[get<1>(top)]});
if(get<0>(top) + 1 < nums1.size()){
pq.emplace(get<0>(top) + 1, get<1>(top), nums1[get<0>(top) + 1] + nums2[get<1>(top)]);
}
--k;
}
return ans;
}
1439. 有序矩阵中的第 k 个最小数组和
该题与上一题类似,唯一的区别是,该题需要将问题分解化,一步一步解决问题,具体可以参考leetcode解答
总结
知识点:
- decltype
- std::initializer_list
- lambda表达式
- priority_queue
- 三种自定义优先队列比较的方式
- emplace方法:vecotr、priority_queue等都有这个方法