题目
1337. 矩阵中战斗力最弱的 K 行 (简单)
给你一个大小为 m * n 的矩阵 mat,矩阵由若干军人和平民组成,分别用 1 和 0 表示。
请你返回矩阵中战斗力最弱的 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
解题思路
- 题中需要求最弱的
k行的索引,那么就要求我们需要统计每一行中军人的数量,由于军人总是排在前面,可以理解为该数组为有序数组,这里采用二分法来快速定位分界点。 - 要按从最弱到最强的顺序进行排序,并且在军人数量一致的情况下,原先位置靠前的行
默认为战力较弱的行,需排在前面,这里就需要利用每一行的军人数量以及当前位置索引值来作为排序的依据。
代码实现
class Solution {
public int[] kWeakestRows(int[][] mat, int k) {
int m = mat.length;
int n = mat[0].length;
int[] counts = new int[m];
// 统计每一行的战斗力
for(int i = 0; i < m; ++i){
// 根据提示mat[i]最大为100,这里用军人数量 * 100,再加上当前位置的索引值
// 方便后面对战斗力进行排序(战斗力相同,位置靠前默认为战斗力较弱)
counts[i] = count(mat[i]) * 100 + i;
}
Arrays.sort(counts);
int[] ans = new int[k];
// 取得最弱 k 行的索引
while(--k >= 0){
// 这里要取余,排除战斗力,取得实际的索引值
ans[k] = counts[k] % 100;
}
return ans;
}
// 二分法统计军人数量
private int count(int[] mat){
int left = 0, right = mat.length - 1;
while(left <= right){
int mid = left + (right - left) / 2;
if(mat[mid] == 0){
right = mid - 1;
}else{
left = mid + 1;
}
}
return left;
}
}
复杂度分析
- 时间复杂度:二分查找
O(m log n)+ 排序O (n log n) - 空间复杂度: 排序数组所用空间
O(m)
最后
文章有写的不好的地方,请大佬们不吝赐教,错误是最能让人成长的,愿我与大佬间的距离逐渐缩短!
如果觉得文章对你有帮助,请 点赞、收藏、关注、评论 一键四连支持,你的支持就是我创作最大的动力!!!