2023-05-28 LeetCode每日一题(有序矩阵中的第 k 个最小数组和)

2023-05-28每日一题

一、题目编号

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

二、题目链接

点击跳转到题目位置

三、题目描述

给你一个 m * n 的矩阵 mat,以及一个整数 k ,矩阵中的每一行都以非递减的顺序排列。

你可以从每一行中选出 1 个元素形成一个数组。返回所有可能数组中的第 k 个 最小 数组和。

四、解题代码

class Solution {
    
    priority_queue<int,vector<int>, greater<int> > q;

    void merge(vector<int> nums1, vector<int> nums2, vector<int> &res, int k){
        for(int i = 0; i < nums1.size(); ++i){
            for(int j = 0; j < nums2.size(); ++j){
                q.push(nums1[i] + nums2[j]);
            }
        }
        int num = 0;
        while(!q.empty() && num < k){
            ++num;
            res.push_back(q.top());
            q.pop();
        }
    }

public:
    int kthSmallest(vector<vector<int>>& mat, int k) {
        int m = mat.size();
        int n = mat[0].size();
        if(m == 1){
            return mat[0][k-1];
        }
        vector<int> res;
        merge(mat[0], mat[1], res, k);
        for(int i = 2; i < m; ++i){
            vector<int> tmp;
            for(int t = 0; t < res.size(); ++t){
                tmp.push_back(res[t]);
            }
            while(res.size() != 0){
                res.pop_back();
            }
            while(!q.empty()){
                q.pop();
            }
            merge(tmp, mat[i], res, k);
        }        
    return res[k-1];
    }
};

五、解题思路

(1) 首先要从不同情况下讨论问题,这是解决这道题目的关键。首先每一行都是排过序的,非递减排序,这意味着我们可以利用上这一点来做一些文章。

(2) 如果数组只有一行,那就是问一维数组的第k个元素,而且本身该数组是一个非递减排序的数组,那么很明显,该问题直接就能够解决了。

(3) 如果数组只有两行,那么就问两个数组各拿出一个元素,第k小的和为多少。这个问题可以用枚举来得到。设置双指针,一个遍历数组1,一个遍历数组2,用优先队列可以帮助我们得到前面k个。

(4) 如果数组有很多很多行呢,那么我们(3)中实际上合并的是两个数组,取前k小的和,那么我们很多行(例如在遍历第x行),相当于是合并的前x-1行的前k小的数字的数组和第x行的数组。那么(3)中所说的数组1就是前x-1行的前k小的和,数组2就是第x行的数组。执行合并即可。

(5) 最后返回的是第n行和前n-1行的前k小的和组成的数组合并后的结果数组的第k小的数字即可。

你可能感兴趣的:(LeetCode每日一题,leetcode,数据结构,算法)