无论在代码简洁度,以及执行用时和内存消耗上均优于官方的两种解法。
class Solution {
//执行用时:0 ms, 在所有 Java 提交中击败了99.99%的用户
//内存消耗:4.8 MB, 在所有 Java 提交中击败了55.20%的用户
//亲测了此题的题解与官方给出的两种题解方式,发现此题无论在代码简洁度,以及执行用时和内存消耗上均优于官方。
// 分享一下我的解题思路:
// 首先容易知道,每行军人的战斗力即是此行一共有多少个1(先不分析存在两行数量相同的军人,在后面会分析),我们可以将这个二维数组的每行1给进行求和算出来,不难想出,二维数组中每行最左边的“0”的索引位置其实就是此行军人的战斗力,所以我们只要找到了这个“0”,便能把此行军人战斗力给算出来,在此,为了优化时间复杂度,创建了一个RowsNum方法,然后使用二分法最后返回最靠左边“0”的索引位置。
// 接着我们可以创建三个数组,其中rank[]用来存储每行军人的战斗力。因为题目要求返回储存按从最弱到最强排序的k个索引数组,所以我们需要创建另一个数组rankSort去储存从小到大排序好了的每行军人战斗力,然后在rankSort[]里去和rank数组里面匹配,匹配到了相同的军人战斗力则可以将原数组rank里面的索引加入到rankIndex数组里面,注意,这里将提到如何解决上述军人战斗力相同的情况,其实我们可以每次在把索引加入到数组rankIndex的同时将此索引对于的值赋值为-1,因为军人战斗力不可能会有负数的情况,然后在下次匹配时就相当于跳过了此索引。
// 最后,其实大概理解了上面的思路就行,通过思路与下面代码相结合就可以更容易掌握一些方法,例如运用到的逆向二分法以及匹配存储索引和解决相同值对应不同索引的方法。
public static int[] kWeakestRows(int[][] mat, int k) {
//创建rank存储每行军人战斗力,方便查找军人战斗力对应的索引
int rank[]=new int[mat.length];
for (int i = 0; i < rank.length; i++) {
rank[i]=RowsNum(mat[i]);
}
//创建rankSort,存储已经排序好了的军人战斗力值
int[] rankSort= Arrays.copyOf(rank,rank.length);
//创建rankIndex存储按题目要求的索引
int[] rankIndex=new int[k];
Arrays.sort(rankSort);
for (int i = 0; i < k; i++) {
for (int j = 0; j < rank.length; j++) {
if(rankSort[i]==rank[j]) {
rankIndex[i] = j;
rank[j]=-1;//以防在匹配下个值时会再次匹配到上次索引的值
break;
}
}
}
return rankIndex;
}
//逆向二分法优化时间复杂度
//创建一个RowsNum方法最终返回值为所有的军人数量值
public static int RowsNum(int[] nums){
int i=0,j=nums.length-1;
int target=0;//target代表最左边的“0”
while (i<=j){
int targetIndex=i+(j-i)/2;
if(nums[targetIndex]>target)
i=targetIndex+1;
else
j=targetIndex-1;
}
return i;//代表此行军人数量
}
}
下一篇:矩阵中战斗力最弱的 K 行
作者:yi-feng-xm
链接:https://leetcode.cn/problems/the-k-weakest-rows-in-a-matrix/solution/zui-you-jie-zhi-ju-zhen-zhong-zhan-dou-l-3yfz/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。