题目描述
给你一个大小为 m * n
的方阵 mat
,方阵由若干军人和平民组成,分别用 0 和 1 表示。
请你返回方阵中战斗力最弱的 k
行的索引,按从最弱到最强排序。
如果第 i
行的军人数量少于第 j
行,或者两行军人数量相同但 i
小于 j
,那么我们认为第 i
行的战斗力比第 j
行弱。
军人 总是 排在一行中的靠前位置,也就是说 1 总是出现在 0 之前。
样例
输入:mat =
[[1,1,0,0,0],
[1,1,1,1,0],
[1,0,0,0,0],
[1,1,0,0,0],
[1,1,1,1,1]],
k = 3
输出:[2,0,3]
解释:
每行中的军人数目:
行 0 -> 2
行 1 -> 4
行 2 -> 1
行 3 -> 2
行 4 -> 5
从最弱到最强对这些行排序后得到 [2,0,3,1,4]
输入:mat =
[[1,0,0,0],
[1,1,1,1],
[1,0,0,0],
[1,0,0,0]],
k = 2
输出:[0,2]
解释:
每行中的军人数目:
行 0 -> 1
行 1 -> 4
行 2 -> 1
行 3 -> 1
从最弱到最强对这些行排序后得到 [0,2,3,1]
限制
m == mat.length
n == mat[i].length
2 <= n, m <= 100
1 <= k <= m
matrix[i][j]
不是 0 就是 1
算法
(二分答案,堆) $O(m (\log n + \log k)))$
- 对于每一行,通过二分求出战斗力。
- 将每一行的战斗力放入一个大小为
k
的大根堆中。如果堆中元素个数等于k
,则比较当前战斗力与堆顶,如果比堆顶小,则堆顶出堆,新插入当前战斗力。 - 最后输出堆中
k
个元素的战斗力
时间复杂度
- 每一行的战斗力需要 $O(m \log n)$ 的时间求出。
- 堆的操作每次的时间复杂度为 $O(\log k)$。
- 总时间复杂度为 $O(m (\log n + \log k))$。
空间复杂度
- 需要额外 $O(k)$ 的空间存储堆和最后的答案。
C++ 代码
class Solution {
public:
vector<int> kWeakestRows(vector<vector<int>>& mat, int k) {
int m = mat.size(), n = mat[0].size();
priority_queue<pair<int, int>> heap;
for (int i = 0; i < m; i++) {
int l = 0, r = n;
while (l < r) {
int mid = (l + r) >> 1;
if (mat[i][mid] == 1) {
l = mid + 1;
} else {
r = mid;
}
}
if (heap.size() < k)
heap.push(make_pair(l, i));
else if (l < heap.top().first) {
heap.pop();
heap.push(make_pair(l, i));
}
}
vector<int> ans;
while (!heap.empty()) {
ans.push_back(heap.top().second);
heap.pop();
}
reverse(ans.begin(), ans.end());
return ans;
}
};
请问一下大佬,priority_queue[HTML_REMOVED]> heap;是根据什么值进行排序的
根据
pair<int, int>
双关键字建大根堆。谢谢大佬