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小的数字即可。