题目描述
给你一个大小为 m * n 的矩阵 mat,矩阵由若干军人和平民组成,分别用 1 和 0 表示。
请你返回矩阵中战斗力最弱的 k 行的索引,按从最弱到最强排序。
如果第 i 行的军人数量少于第 j 行,或者两行军人数量相同但 i 小于 j,那么我们认为第 i 行的战斗力比第 j 行弱。
军人 总是 排在一行中的靠前位置,也就是说 1 总是出现在 0 之前。
示例 1:
输入: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]
示例 2:
输入: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
来源:力扣(LeetCode)
题目大意
一个m*n的二维数组,由0和1组成,求每行的总值最小的前k个数(1恒在0前)
思路描述
思想很简单,但是官方题解就很花哨了使用的是二分法+快速选择的方式
我的思想为元组+排序的方式
时间复杂度上:
官方题解的时间复杂度为O(m log n + k log k“)
我的时间复杂度为*O(m log m” + n m)
我的思路:
将每一行的数都加起来放到一个数组中,将数组排序选出来前k个数
我的解题步骤:
- 创建一个<当前行的总值,当前行的下标>的元组node
- 找到所有行的总值
- 创建以这个元组node为数值的list数组
- 以当前行的总值->当前行的下标的优先级自定义排序
- 创建返回值数组rlist
- 将得到的list数组的前k项放入返回值数组rlist中
- 返回rlist
官方思路:
找到每一行0与1的分界点,记录下标值,使用快速选择快速选择出前n个小的数值,对选择出来的数据排序输出
官方解题步骤:
- 使用二分法找到0和1的分界点
- 分界点下标就是该行总值
- 将所有行的总值使用快速选择选出前k个值
- 将选出来的k个值进行排序记录到rlist数组中
- 输出rlist数组
代码
class Solution {
//1:创建一个<当前行的总值,当前行的下标>的元组node
class node{
int val;
int i;
public node(int val,int i){
this.val=val;
this.i=i;
}
}
public int[] kWeakestRows(int[][] mat, int k) {
//2:创建以这个元组node为数值的list数组
node[] list=new node[mat.length];
//3:找到所有行的总值
for(int i=0;i<mat.length;i++){
int currentX=0;
for(int i1=0;i1<mat[i].length;i1++){
if(mat[i][i1]==0){
break;
}
currentX++;
}
list[i]=new node(currentX,i);
}
//4:以当前行的总值->当前行的下标的优先级自定义排序
Arrays.sort(list,new Comparator<node>(){
@Override
public int compare(node o1, node o2) {
// TODO Auto-generated method stub
if(o1.val!=o2.val){
return o1.val-o2.val;
}
if(o1.i!=o2.i){
return o1.i-o2.i;
}
return 0;
}
});
//5:创建返回值数组rlist
int[] rlist=new int[k];
//6:将得到的list数组的前k项放入返回值数组rlist中
for(int i=0;i<k;i++){
rlist[i]=list[i].i;
}
//7:输出rlist数组
return rlist;
}
}
写在最后
如果感觉写的还不错的话不妨分享给其他人,以求共同进步!
文章如有错误之处请指出,我会听取并改正!