在二维矩阵/数组中查找元素 Leetcode74, Leetcode240

这一类题型中二维数组的元素取值有序变化,因此可以用二分查找法。我们一起来看一下。

一、Leetcode 74

Leetcode 74. 搜索二维矩阵 这道题要在一个二维矩阵中查找元素。该二维矩阵有如下特点:

  • 每行元素 从左到右 按非递减顺序排列。
  • 每行的第一个元素 > 前一行的最后一个元素。

也就是说,这种二维数组的元素逐行、逐列递增变化,如下图所示,沿箭头方向元素值递增:

在这里插入图片描述

方法一:做两次二分查找。
  • 先在第一列中查找值为 target 的元素所在行。
  • 再在这一行中查找值为 target 的元素所在列。

在这两步中,难点在于第一步确定 target 所在行。以图中的示例矩阵为例,要寻找 3,如何定位到 3 所在行呢?在第一列的元素中,3 所在行的第一列元素 1 是小于 3 的元素中最接近 3 的元素,这就是第一步的思路:在第一列元素中查找小于等于 target、且最接近 target 的元素。这里可以用 Leetcode 69 所使用的方法(欢迎阅读文章:二分查找法搜寻元素 Leetcode35, Leetcode69,其中详细介绍了这类问题的两种解决方法,本文采用了其中一种方法。)

相应的 Python 代码和注释为:

class Solution:def searchMatrix(self, matrix: List[List[int]], target: int) -> bool:# 第一步:查找元素所在行low, high = 0, len(matrix) - 1while low <= high:mid = low + (high - low) // 2# 注意:这里是在第 1 列查找,# mid元素索引为 matrix[mid][0]。if matrix[mid][0] == target:return Trueelif matrix[mid][0] > target:high = mid - 1else:low = mid + 1# 确定元素所在行(row)row = high# 第二步:查找元素所在列low, high = 0, len(matrix[0]) - 1while low <= high:mid = low + (high - low) // 2# 注意:这里是在第 row 行查找,# mid元素索引为 matrix[row][mid]。if matrix[row][mid] == target:return Trueelif matrix[row][mid] > target:high = mid - 1else:low = mid + 1return False         
方法二:把二维矩阵看作一个一维数组处理。

因为矩阵的元素是按升序排列,我们在处理时可以把它想象成连续的一维序列,就像上图示例矩阵中的元素,在脑子里把它“拼接”成一个连续的一维数组,[1,3,5,7,10,11,16,20,23,30,34,60],在这个升序数组里查找元素很容易。

但是,这个一维数组索引只是我们为了解决问题做的设想,实际中矩阵元素是以二维数组形式存储的,因此每次索引元素值时还需要一个操作:把(设想的)一维数组索引换算回(实际的)二维数组索引。

相应的 Python 代码和注释为:

class Solution:def searchMatrix(self, matrix: List[List[int]], target: int) -> bool:# 求 mxn 矩阵的维度大小m = len(matrix)n = len(matrix[0])# 按“一维”有序数组处理length = m*nlow, high = 0, length - 1while low <= high:mid = low + (high - low) // 2# 关键:索引时要把(设想的)一维数组索引换算回(实际的)二维数组索引。mid_row = mid // nmid_col = mid % nmid_val = matrix[mid_row][mid_col] if mid_val == target:return Trueelif mid_val > target:high = mid - 1else:low = mid + 1return False           

方法二实现起来比方法一更简洁,但是我在 Leetcode 运行代码时发现方法二比方法一的耗时大。

二、Leetcode 240

Leetcode 240. 搜索二维矩阵 II 这道题也是在二维矩阵中查找元素。不同的是,这里的二维矩阵有如下特点:

  • 每行的元素 从左到右 升序排列。
  • 每列的元素 从上到下 升序排列。

下图所示为一个示例矩阵:

在这里插入图片描述

这道题的巧妙之处在于中点 mid 的选择

根据给定矩阵的升序排列特点,一个元素位于第 i 行、第 j 列,则该元素所在行第 0 ~ ( j - 1 ) 列的元素都比它小;该元素所在列第 ( i + 1 ) ~ ( m - 1 ) 行的元素都比它大。具体来说,以上图的示例矩阵为例,如绿色箭头标识所示,以圆圈中的元素 8 为中点,[ 2, 5, 8, 9, 14, 23 ] 这些元素就构成了一个升序排列的数组。也就是说,以第 i 行、第 j 列的元素为直角,其所在行和列元素构成的 倒 “L” 形状序列 是一个有序数组,而在直角的这个元素就是数组的中点。在这个数组中可以用二分查找:比较中点的元素与目标值 target 的大小决定下一步的寻找范围。如果该元素大于 target,就往左移一列:j - 1。如果该元素小于 target,就往下移一行:i + 1。

应该从哪里开始呢?选择右上角的元素(第 0 行,(n-1) 列)做为起始 mid 元素,逐步推进到左下角元素。时间复杂度是 O(m+n)。这一点您可以试一下,如果要找的元素位于左下角,正好要走 m+ n 步。

相应的 Python 代码为:

class Solution:def searchMatrix(self, matrix: List[List[int]], target: int) -> bool:m, n = len(matrix), len(matrix[0])i, j = 0, n - 1while i < m and j >= 0:if matrix[i][j] == target:return Trueelif matrix[i][j] > target:j -= 1else:i += 1return False             

本文对您有帮助的话,请点赞支持一下吧,谢谢!

关注我 宁萌Julie,互相学习,多多交流呀!

参考

1.Leetcode 74 方法二思路:Don’t treat it as a 2D matrix, just treat it as a sorted list - Search a 2D Matrix - LeetCode

2.Leetcode 240 思路:My concise O(m+n) Java solution - Search a 2D Matrix II - LeetCode

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/159958.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

速学数据结构 | (超级干货)业界程序员公认的实现栈最简单的方法!太简单了

&#x1f3ac; 鸽芷咕&#xff1a;个人主页 &#x1f525;个人专栏:《Linux深造日志》《C干货基地》 ⛺️生活的理想&#xff0c;就是为了理想的生活! &#x1f4cb; 前言 &#x1f308;hello&#xff01; 各位铁铁们大家好啊&#xff0c;今天来给大家更新一下栈这个数据结构,…

STM32笔记-AD模数转换

目录 一、ADC介绍 二、ADC主要特征 三、ADC框图 1. ​​​​ 外部触发转换 ​ 2. 转换模式 3. 输入通道 4. 逻辑框图 四、校准 五、数据对齐 六、AD转换步骤 七、AD_Init(单通道AD转换)初始化函数配置 一、ADC介绍 1. 12位ADC是一种逐次逼近型模拟数字转换器。它有多达…

R语言中的自带的调色板--五种--全平台可用

R语言中的自带的调色板–五种–全平台可用

逆袭Flutter? Facebook 发布全新跨平台引擎 Hermes!

Facebook 于前日发布了新的 JavaScript 引擎&#xff1a;Hermes&#xff0c;专注于提高 React Native 应用的性能&#xff0c;并且在市面上那些内存较少、存储速度较慢且计算能力低下的移动设备上都有良好的表现。但是不是为了追赶Flutter&#xff1f;这块作者没有说明。 移动应…

天空卫士为集度智能汽车系上“安全带”

10月27日&#xff0c;集度汽车在北京正式发布了旗下首款量产车型——极越 01 SUV。极越 01 SUV 是一款集科技、智能、美学于一身的纯电动中大型SUV&#xff0c;号称全球首款“AI 汽车机器人”。作为集度的合作伙伴&#xff0c;天空卫士第一时间送上祝福&#xff0c;祝愿极越大卖…

ElasticSearch深度解析入门篇:高效搜索解决方案的介绍与实战案例讲解,带你避坑

ElasticSearch深度解析入门篇&#xff1a;高效搜索解决方案的介绍与实战案例讲解&#xff0c;带你避坑 1.Elasticsearch 产生背景 大规模数据如何检索 如&#xff1a;当系统数据量上了 10 亿、100 亿条的时候&#xff0c;我们在做系统架构的时候通常会从以下角度去考虑问题&a…

根据Word模板,使用POI生成文档

突然想起来有个小作业&#xff1a;需要根据提供的Word模板填充数据。这里使用POI写了一个小demo验证下。 测试用模板&#xff1a; 执行结果 1.引入依赖坐标 <dependency><groupId>org.apache.poi</groupId><artifactId>poi-ooxml</artifactId&…

初学Flutter:swiper实现

效果展示&#xff1a; flutter swiper 1、安装 card_swiper 2、引入card_swiper import package:card_swiper/card_swiper.dart;3、使用 这里我主要是对官网例子进行实践&#xff0c;主要是5种常用的swiper 1、普遍的swiper //custom swiper class CustomSwiper extends S…

代码随想录算法训练营第23期day38|动态规划理论基础、509. 斐波那契数、70. 爬楼梯、746. 使用最小花费爬楼梯

目录 一、动态规划理论基础 1.动态规划的解题步骤 2.动态规划应该如何debug 二、&#xff08;leetcode 509&#xff09;斐波那契数 1.递归解法 2.动态规划 1&#xff09;确定dp数组以及下标的含义 2&#xff09;确定递推公式 3&#xff09;dp数组如何初始化 4&#x…

20.5 OpenSSL 套接字RSA加密传输

RSA算法同样可以用于加密传输&#xff0c;但此类加密算法虽然非常安全&#xff0c;但通常不会用于大量的数据传输&#xff0c;这是因为RSA算法加解密过程涉及大量的数学运算&#xff0c;尤其是模幂运算&#xff08;即计算大数的幂模运算&#xff09;&#xff0c;这些运算对于计…

HTTP 协议请求头 If-Match、If-None-Match 和 ETag

概述 在 HTTP 协议中&#xff0c;请求头 If-Match、If-None-Match、If-Modified-Since、If-Unmodified-Since、If-Range 主要是为了解决浏览器缓存数据而定义的请求头标准&#xff0c;按照协议规范正确的判断和使用这几个请求头&#xff0c;可以更精准的处理浏览器缓存&#x…

【OpenApi Generator】入门和调试

OpenApi Generator是什么 OpenAPI Generator 是一个完全免费开源 (Apache 许可 v2) 的项目&#xff0c;用来生成 REST1 API 客 户端、服务器存根和基于 OpenAPI (以前称为 Swagger ) 规范的文档。如果您不熟悉 OpenAPI 规范&#xff0c;那么它就是描述 RESTful API 方面最流…