Leetcode最优解之矩阵中战斗力最弱的k行(逆向二分思维+快速排序

该文章介绍了一种Java解决方案,该方案在处理寻找矩阵中战斗力最弱的K行问题时,无论在代码简洁度、执行速度(0ms,99.99%的Java提交被击败)还是内存使用(4.8MB,击败55.20%的Java提交)上都优于官方解法。关键策略包括使用二分法找到每行的战斗力(即1的数量),并用排序和索引处理相同战斗力的情况来找到最弱的行。
摘要由CSDN通过智能技术生成

无论在代码简洁度,以及执行用时和内存消耗上均优于官方的两种解法。
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)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值