1439. 有序矩阵中的第 k 个最小数组和

123 阅读2分钟

有序矩阵中的第 k 个最小数组和

主要内容:

  1. 373. 查找和最小的 K 对数字
  2. 1439. 有序矩阵中的第 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]

直接先上代码

  1. 优先队列——自定义比较函数

解题思路可参考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解答

总结

知识点: