1、描述
给你一个大小为 m * n 的矩阵 mat,矩阵由若干军人和平民组成,分别用 1 和 0 表示。
请你返回矩阵中战斗力最弱的 k 行的索引,按从最弱到最强排序。
如果第 i 行的军人数量少于第 j 行,或者两行军人数量相同但 i 小于 j,那么我们认为第 i 行的战斗力比第 j 行弱。
军人 总是 排在一行中的靠前位置,也就是说 1 总是出现在 0 之前。
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/the-k-weakest-rows-in-a-matrix
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
2、关键字
矩阵,前k个元素,
3、思路
看到前k个元素,就想到优先队列,STL中使用大顶堆实现优先队列,
priority_queue<T> que; // 默认大顶堆,队列从大到小排列。
如果想使用从小到大排列:
priority_queue<T,vector<T>,greater<T> > que;
大顶堆是从大到小,二叉树的结构,但是存储是使用线性结构的队列。
4、notes
直接使用优先队列。
默认大顶堆,从大到小排列。
如果需要自定义排序算法,从小到大,需要写成大于号。
第三个参数:谓词,可以是函数,也可以是lamba表达式的名字
而自己写的使用冒泡排序也是稳定的但是没过。
5、复杂度
时间:O(max(nm,nlgn)),首先遍历了一遍矩阵,复杂度 O(nm),将每行存入优先队列复杂度 O(nlgn)。
空间:O(N)
6、code
优先队列大顶堆
class Solution {
public:
vector<int> kWeakestRows(vector<vector<int>>& mat, int k) {
priority_queue<pair<int,int> >que; // 构造优先队列的基本元素pair
vector<int>res;
int n = mat.size();
for(int i = 0; i < n; i++){ // 遍历mat 组装 优先队列的基本元素
int cnt = 0;
for(auto elem : mat[i]){
cnt += elem;
}
que.push({cnt,i}); // 使用的是push方法
}
while(que.size() > k) que.pop(); // STL默认大顶堆,如此把强队删除,
while(!que.empty()){
res.push_back(que.top().second);
que.pop();
}
reverse(res.begin(),res.end());
return res;
}
};
改写成为小顶堆 的优先队列:
1、自定义比较函数:使用一个auto关键字 + lamba表达式
2、使用自定义排序的优先队列时候的3个参数,
class Solution {
public:
vector<int> kWeakestRows(vector<vector<int>>& mat, int k) {
auto cmp = [](pair<int,int> & a,pair<int,int>& b){
if(a.first == b.first){
return a.second > b.second; // 这里一个奇怪的现象,明明说的是变成从小到大排序,却要写成 大于号!
}
else{
return a.first > b.first;
}
}; // 这里有一个分号
priority_queue < pair<int,int>, vector<pair<int,int> >,decltype(cmp) > que(cmp); // 构造优先队列的基本元素pair
//priority_queue<pair<int,int> vector<pair<int,int>,greator<pair<int,int>> >que;// 构造优先队列的基本元素pair
vector<int>res;
int n = mat.size();
for(int i = 0; i < n; i++){ // 遍历mat 组装 优先队列的基本元素
int cnt = 0;
for(auto elem : mat[i]){
cnt += elem;
}
que.push({cnt,i}); // 使用的是push方法
}
for(int i = 0; i< k; i++){
res.push_back(que.top().second);
que.pop();
}
return res;
}
};