题目:

给你一个大小为 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个元素

力扣1337(java&python)-矩阵中战斗力最弱的 K 行(简单)的更多相关文章

  1. LeetCode1337矩阵中最弱的K行

    题目 给你一个大小为 m * n 的矩阵 mat,矩阵由若干军人和平民组成,分别用 1 和 0 表示. 请你返回矩阵中战斗力最弱的 k 行的索引,按从最弱到最强排序. 如果第 i 行的军人数量少于第 ...

  2. 力扣(LeetCode)字符串中的单词数 个人题解

    统计字符串中的单词个数,这里的单词指的是连续的不是空格的字符. 请注意,你可以假定字符串里不包括任何不可打印的字符. 示例: 输入: "Hello, my name is John" ...

  3. 力扣(LeetCode)字符串中的第一个唯一字符 个人题解

    给定一个字符串,找到它的第一个不重复的字符,并返回它的索引.如果不存在,则返回 -1. 案例: s = "leetcode" 返回 0. s = "loveleetcod ...

  4. python爬虫中scrapy框架是否安装成功及简单创建

    判断框架是否安装成功,在新建的爬虫文件夹下打开盘符中框输入cmd,在命令中输入scrapy,若显示如下图所示,则说明成功安装爬虫框架: 查看当前版本:在刚刚打开的命令框内输入scrapy versio ...

  5. Python 数据分析中金融数据的来源库和简单操作

    目录 金融数据 pandas-datareader TuShare 金融学图表 案例 金融数据 数据分析离不开数据的获取,这里介绍几种常用的获取金融方面数据的方法. pandas-datareader ...

  6. 力扣 - 剑指 Offer 54. 二叉搜索树的第k大节点

    题目 剑指 Offer 54. 二叉搜索树的第k大节点 思路1 二叉搜索树的特性就是中序遍历结果为递增序列,而题目要求的是第 k 大节点,所以就应该是要遍历结果为降序, 按照先遍历左子树.输出节点.遍 ...

  7. 找到排序矩阵中从小到大第K个数字

    一 题目描述 在一个排序矩阵中找从小到大的第 k 个整数. 排序矩阵的定义为:每一行递增,每一列也递增. 二 题解 由于排序矩阵中的每一行都是递增的,并且每一列都是递增的.从小到大第k个数,实际上就是 ...

  8. 排序矩阵中的从小到大第k个数 · Kth Smallest Number In Sorted Matrix

    [抄题]: 在一个排序矩阵中找从小到大的第 k 个整数. 排序矩阵的定义为:每一行递增,每一列也递增. [思维问题]: 不知道应该怎么加,因为不是一维单调的. [一句话思路]: 周围两个数给x或y挪一 ...

  9. lintcode-401-排序矩阵中的从小到大第k个数

    401-排序矩阵中的从小到大第k个数 在一个排序矩阵中找从小到大的第 k 个整数. 排序矩阵的定义为:每一行递增,每一列也递增. 样例 给出 k = 4 和一个排序矩阵: [ [1 ,5 ,7], [ ...

  10. 在java.ext.dirs中使用环境变量导致crontab执行不成功的问题及解决

    在java.ext.dirs中使用环境变量导致crontab执行不成功的问题及解决 Table of Contents 1. java.ext.dirs的使用和环境变量 2. 问题:在crontab中 ...

随机推荐

  1. 脑电测量ADS1299芯片调试总结

    问题一:读出来ID不对? 笔者经过查阅官网资料和测试,发现这个一般是上电或者启动次序不对引起的. 特别是上电次序不同会导致这类问题. 问题二:内部时钟和外部时钟的选择是什么? 就拿内部时钟来说吧,首先 ...

  2. Python 的结构体函数 struct pack, unpack 用法详解

    一 python 结构体 * python struct 模块可以用来在存储二进制文件,广泛用在文件系统,网络连接领域. *  它可以用在c语言和python语言之间的数据的格式转换. 二  Pyth ...

  3. Android 设置任意View的背景为圆形或圆角

    原文地址: Android 设置任意View的背景为圆形或圆角 - Stars-One的杂货小窝 我的需求主要还是在SurfaceView需要设置为圆形背景,在网上找了下,发现一个可行方法,做个记录 ...

  4. Web服务器通信原理

    Web服务器通信原理 1.区分系统 2.DOS系统 3.IP地址 4.域名.DNS 5.端口 6.HTTP协议 7.Web容器 8.整个流程 一.区分系统 主要三个系统Windows.Linux.Ma ...

  5. Python编程规范+最佳实践

    前言 Python之禅是影响Python编程语言设计的19条原则,也是Python编码规范的核心理念. 优美胜于丑陋(Python 以编写优美的代码为目标) 明了胜于晦涩(优美的代码应当是明了的,命名 ...

  6. 舒服了,学习了,踩到一个 Lombok 的坑!

    你好呀,我是歪歪. 踩坑了啊,最近踩了一个 lombok 的坑,有点意思,给你分享一波. 我之前写过一个公共的服务接口,这个接口已经有好几个系统对接并稳定运行了很长一段时间了,长到这个接口都已经交接给 ...

  7. 不用写一行代码!Python最强自动化神器!

    1.Playwright介绍 Playwright是一个由Microsoft开发的开源自动化测试工具,它可以用于测试Web应用程序.Playwright支持多种浏览器,包括Chrome.Firefox ...

  8. AntvG6-graph图谱工具

    1 快速上手 1.1 在项目中使用 npm 包引入 Step 1: 使用命令行在项目目录下执行以下命令 npm install --save @antv/g6 Step 2: 在需要用的 G6 的 J ...

  9. C++设计模式 - 解析器模式(Interpreter)

    领域规则模式 在特定领域中,某些变化虽然频繁,但可以抽象为某种规则.这时候,结合特定领域,将问题抽象为语法规则,从而给出在该领域下的一般性解决方案. 典型模式 Interpreter Interpre ...

  10. #dp,齐肯多夫定理#CF126D Fibonacci Sums

    题目 \(T(T\leq 10^5)\) 组数据,每次给定数字 \(n(n\leq 10^{18})\), 问有多少种方案将 \(n\) 分解成若干个互不相同的斐波那契数 分析 如果找到一个方案使得所 ...