首页 > 编程语言 >力扣1337(java&python)-矩阵中战斗力最弱的 K 行(简单)

力扣1337(java&python)-矩阵中战斗力最弱的 K 行(简单)

时间:2022-12-05 15:57:47浏览次数:48  
标签:right java mat python 1337 mid pos int left

题目:

给你一个大小为 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)
链接:https://leetcode.cn/problems/the-k-weakest-rows-in-a-matrix
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

解题思路:

根据题目中的意思:军人总是排在一行中的靠前位置,1 总是出现在 0 之前,且二维矩阵中不是0就是1。就可以用二分查找,找出一行中最后一个1 的位置,设置位置的初始值pos为-1,则得知最后一个1的位置后,这一行1的个数就为pos+1。

二分查找的细节:

  • 设置left = 0, right = col - 1, pos = -1, mid = left + (right - left + 1) / 2;
  • 循环的条件是:left < right;
  • 如果 mat[i][mid] == 0,则说明mid右边的数都为0,需要移动right到mid-1,搜索范围为[left, mid -1];
  • 如果 mat[i][mid] == 1,则说明mid左边的数都为1,但是mid也有可能是最后一个1的位置,故将 left 移动到 mid,搜索范围为[mid, right](所以mid需要向上取整);
  • 循环结束后:left == right,需要判断left处的值是否为1,为1则pos = left,否则pos还是循环中的pos。

得到每一行的战斗力后,可以将每一行的战斗力和其索引放入到一个小跟堆里面,但是当战斗力相同时,索引较小的更弱,故需要在小根堆中存放战斗力和索引的二元组。

java代码(left < right):

 1 class Solution {
 2     public int[] kWeakestRows(int[][] mat, int k) {
 3         int row = mat.length, col = mat[0].length;
 4         //建立一个小跟堆
 5         PriorityQueue<int[]> queue = new PriorityQueue<>((x1, x2) -> {
 6             //如果两行个数不相同,就按照个数升序
 7             if (x1[0] != x2[0]){
 8                return x1[0] - x2[0];
 9             } else {
10                 //如果两行个数相同,就按照行索引升序
11                return x1[1] - x2[1];
12             }
13         });
14         //二分查找,找到每行1的个数
15         for (int i = 0; i < row; i++){
16             int pos = -1;
17             int left = 0, right = col - 1;
18             while (left < right){
19                 int mid = left + (right - left + 1) / 2;
20                 if (mat[i][mid] == 0){
21                     right = mid - 1;
22                 }else {
23                     left = mid;
24                     //更新pos的位置
25                     pos = mid;
26                 }
27             }
28             pos = mat[i][left] == 1 ? left : pos;
29             //pos+1:pos为位置,pos+1就为长度
30             queue.offer(new int[]{pos+1, i});
31         }
32         int[] res = new int[k];
33         for (int l = 0; l < k; l++){
34             res[l] = queue.poll()[1];
35         }
36         return res;
37     }
38 }

 python3代码(left <= right):

 1 class Solution:
 2     def kWeakestRows(self, mat: List[List[int]], k: int) -> List[int]:
 3         row, col = len(mat), len(mat[0])
 4         power = list()
 5         for i in range(row):
 6             left, right, pos = 0, col-1, -1
 7             while left <= right:
 8                 mid = left + (right - left) // 2
 9                 if mat[i][mid] == 0:
10                     right = mid - 1
11                 else:
12                     left = mid + 1
13                     pos = mid
14             power.append((pos+1, i))
15         # 将列表转换为堆
16         heapq.heapify(power)
17         res = list()
18         for i in range(k):
19             res.append(heapq.heappop(power)[1])
20         return res

 小知识:

1.java使用优先队列实现大顶堆和小顶堆,默认是小根堆,当然记不住默认也没有关系

小根堆创建:

 PriorityQueue<Integer> minHeap = new PriorityQueue<>(k,(a,b) -> a-b);

大跟堆创建:

PriorityQueue<Integer> maxHeap = new PriorityQueue<>(k,(a,b) -> b-a);

其中构造器中的k表示创建堆的大小,之后用Lambda表达式快速实现自定义排序。

2.heapq堆的常用方法:

  • heapq.heapify(list): 将列表转换为堆
  • heapq.heappush(heap, itme):heap为定义堆,item增加的元素
  • heapq.heappop(heap):删除并返回最小值,因为堆的特征是heap[0]永远是最小的元素,所以一般都是删除第一个元素
  • heapq.heapreplace(heap.item) :删除并返回最小元素值,添加新的元素值
  • heap.heappushpop(list, itme):判断添加元素值与堆的第一个元素值对比;如果大,则删除并返回第一个元素,然后添加新元素值item;如果小,则返回item,原堆不变
  • heap.nlargest(n, heap):查询堆中的最大n个元素
  • heap.nsmallest(n, heap):查询堆中的最小n个元素

标签:right,java,mat,python,1337,mid,pos,int,left
From: https://www.cnblogs.com/liu-myu/p/16952365.html

相关文章

  • Python如何把类的一个方法变为属性?
    需求:Python如何把类的一个方法变为属性?解决:用@property装饰器(property财产 [ˈprɒpəti])classobj:def__init__(self,host):self.host=hos......
  • python处理pom.xml文件
    #coding=utf-8#@author:今夕#@Time:2022.12.0510:40#@file:test.py.py#@software:PyCharmimportosimpor......
  • JavaDoc生成文档
    JavaDoc生成文档一.通过命令行生成JavaDoc文档1.打开指定的文件目录选中指定文件(类或者包)--->右键选中openin---->explorer2.打开指定文件的cmd再1中打开的文......
  • python中ImmutableMultiDict嵌套字典的值获取和解决400状态码的问题
    在写接口的过程中遇到了一次请求状态码400原因是用elementupload组件上传照片,后端采用flask的时候用request.form读取上传携带的其他参数,data=request.formtitle=......
  • JavaScript深浅拷贝
    基本类型&引用类型ECMAScript中的数据类型可分为两种:基本类型:undefined,null,Boolean,String,Number,Symbol引用类型:Object,Array,Date,Function,RegExp等不同类......
  • java面试
    目录枚举泛型用反射动态给对象的某个属性赋值导包带*有什么影响idea如何取消自动导包为*BIO和NIO和AIO枚举点击查看代码packagecom.cdjdgm.pdms.enums;/***供电......
  • 如何通过Java将Word转换为PDF
    Word是我们日常编辑文档内容时十分常用的一种文档格式。但相比之下,PDF文档的格式、布局更为固定,不易被更改。在保存或传输较为重要的文档内容时,PDF文档格式也时很多人的不......
  • Ubuntu20.04 编译安装 CPython3.10.8(WSL2)
    CPython,由C编写的python发行版,通过在github下载源代码,通过cmake进行打包安装1.ubuntu安装编译工具:sudoapt-get installlibssl-devzlib1g-devlibbz2-devlibreadl......
  • python-面向对象-类的多态-父类方法重写,继承多态的表现形式
    1.类的多态python面向对象的多态依赖于继承,因为继承,使得子类拥有了父类的方法,子类的方法与父类方法重名时是重写,同一类事物,有多重形态,这就是面向对象概念里的多......
  • Java 8 stream 合并map 分组计算
    Map<String,Map<String,Long>>map=newHashMap<>();Map<String,Long>param1=newHashMap<>();param1.put("a",100L);param1.put("b",200L);param1.put("c......