算法题解记录18+++搜索二维矩阵Ⅱ

        本题可以说是运用二分查找的典例,即使是面对矩阵,只要是它保持“排序好”这样的结构,就一定能采用二分查找法。【你知道的,对于排序好的数组,二分查找几乎是最优秀的算法】

        当然,答案提供的是“Z字形查找法”【这个概念我搜不到,不过其实质,就是矩阵边界的缩减】

        “Z字形”排查效率高于二分查找法,只是因为题目结构特殊,一般不会有这种结构。

题目描述:

        编写一个高效的算法来搜索 m x n 矩阵 matrix 中的一个目标值 target 。该矩阵具有以下特性:

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

示例 1:

输入:matrix = [[1,4,7,11,15],[2,5,8,12,19],[3,6,9,16,22],[10,13,14,17,24],[18,21,23,26,30]], target = 5
输出:true

示例 2:

输入:matrix = [[1,4,7,11,15],[2,5,8,12,19],[3,6,9,16,22],[10,13,14,17,24],[18,21,23,26,30]], target = 20
输出:false

提示:

  • m == matrix.length
  • n == matrix[i].length
  • 1 <= n, m <= 300
  • -10^9 <= matrix[i][j] <= 10^9
  • 每行的所有元素从左到右升序排列
  • 每列的所有元素从上到下升序排列
  • -10^9 <= target <= 10^9

解题准备:

        1.理解题意:本题的结构,非常特殊,对于matrix中的任一元素【i,j】,其具备四个属性,上、左的元素小于它,下、右的元素大于它【对于边界元素不讨论,类似】

        2.理解可能具备的操作:就此,大概率只需要查找一种操作即可。

        3.朴素的思路:对于矩阵,最简单的遍历原则就是,暴力遍历【从0行到len-1行,从0列到len2-1列,依次遍历元素】

        代码为:

for(int i=0; i<m; i++){for(int j=0; j<n; j++){// m是行数,n是列数。// 在这个语句段里操作}
}

        不过,虽然这样做,一定能找到target(或者发现根本没有),却浪费了约束条件:每一行、列存在递增的关系。

解题难点1分析:

        如果不从二分查找的角度,对于这种结构比较容易想到的优化方法为:

        1.遍历第0行的元素,依次判断大小(如果< target,+1),如果等于target直接返回true,如果大于target说明这一行不可能存在target,遍历下一行。

        2.接着上述,遍历第1行,同理……

        问题:时间复杂度仍高

                对于这种优化方案,如果是下图的结构:

                容易发现,其遍历次数与暴力for一样多,所以时间复杂度的优化很差。

                就算是一般的结构,如果target比较大,很大概率前面k行,也得全部遍历(k随机),也就是说,时间复杂度没怎么优化。从最差优化的角度分析,时间复杂度仍是O(m*n);

        没办法,这种优化不可取,得从别的角度出发。

解题难点2分析:

        从二分查找的角度出发,既然行列间满足递增的约束,那么对于每一行,必然也满足递增的约束。

        拆分每一行,拆成0到len-1行,每一行用二分查找查找,时间复杂度为O(logN)。

        由于遍历0到len-1行,所以总的时间复杂度是O(m * log n);

        代码在此不写了,比较简单。

        不过,这道题是个强约束,拆分后,反而增加了查找时间复杂度。

解题难点3分析:

        从结构本身出发,由于行列间递增,那么,应该能处理特殊的数据。

        什么意思呢?我们用【0,0】,【0,len-1】,【len2-1,0】,【len-1,len2-1】维护矩阵的四个角的数据。

        由于矩阵的特殊性质,我们知道:【0,0】一定是最小的,【0,len-1】一定是0行最大的,【len2-1,0】一定是0列最大的,【len-1, len2-1】一定是所有数据最大的。

        如果矩阵中存在target,那么它一定大于【0,0】,小于【len-1,len2-1】。

        如果target大于【0, len-1】呢?这说明,target大于0行所有元素,那需要继续查找0行吗?

        可以直接忽略,从第1行开始查找。

        不过,target可能小于【0, len-1】,同时大于【0, 0】,这说明它可能在第0行。

        这时候从【len2-1, 0】开始判断,问题又来了:可能target同时大于【0,0】,小于【len2-1,0】

        不过,如果target小于【len2-1, 0】,不就说明:第len2-1行,都比target大吗?(因为【len2-1,0】在该行最小)

        那么,往上移动一行,不就行了?        

        其实从这个角度,看【0, len-1】也一样,如果target小于【0,len-1】,不就说明target小于len-1列的所有元素吗?

        往回退一列,不就行了?

        为了保持一致性,建议在四个角中,拿一个元素操作即可。

        该算法,每次可以排除一行或者一列,效率更高一些。

以上内容即我想分享的关于力扣热题18的一些知识。

        我是蚊子码农,如有补充,欢迎在评论区留言。个人也是初学者,知识体系可能没有那么完善,希望各位多多指正,谢谢大家。

        

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

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

相关文章

实在Agent:超自动化智能体的革命(附导引指南)

在自动化技术的浪潮中&#xff0c;实在智能推出了实在Agent&#xff08;智能体&#xff09;&#xff0c;一款基于大语言模型和屏幕语义理解技术的超自动化智能体。它通过自然对话交互&#xff0c;将复杂工作简化为一句话指令&#xff0c;自动规划并执行工作任务&#xff0c;极大…

C++奇迹之旅:深入理解赋值运算符重载

文章目录 &#x1f4dd;赋值运算符重载&#x1f320; 运算符重载&#x1f309;特性 &#x1f320; 赋值运算符重载&#x1f320;传值返回&#xff1a;&#x1f320;传引用赋值&#xff1a;&#x1f309;两种返回选择&#x1f309;赋值运算符只能重载成类的成员函数不能重载成全…

【御控物联】物联网数据传输数据格式

随着物联网技术的快速发展&#xff0c;越来越多的系统和设备被接入到了物联网管理中&#xff0c;数据交换与共享成为了一个重要的问题。不同的设备和系统之间存在着各种各样的通信协议和数据格式&#xff0c;这就给数据获取、交换和共享带来了很大的不便利。 MQTT 是机器对机器…

unity学习(86)——细节优化

东西已经做出来了&#xff0c;现在需要的是优化&#xff0c;说得简单&#xff0c;做起来难。 1.122包的优化&#xff0c;避免重复创建&#xff01; 2.为何会出现一边动&#xff0c;一边不动的情况。重复登录后依旧是unity可以看到移动&#xff0c;但是exe那边看不到移动&#…

关于图像YUV格式分类和排布方式的全学习

【学习笔记】关于图像YUV格式分类和排布方式的全学习_yuv图像-CSDN博客 下图是将多个yuv420p图像(A和B)&#xff0c;拼接成一个画面的思路 A大小:416*64 B大小:416*208 将A和B合并到一个416*416的尺寸上&#xff0c;代码如下 //整合char * ptd;ptd (char * ) malloc (416*41…

C#通用类库封装实战

数据库查询 特性方式获取数据库列的别名 数据库更新 使用简单工厂配置的方式

套接字基础

套接字基础 套接字一、socket二、setsockopt三、bind四、listen五、select六、poll七、epoll一、水平模式&#xff08;Level-Triggered&#xff0c;LT&#xff09;二、边沿模式&#xff08;Edge-Triggered&#xff0c;ET&#xff09; 套接字 最近学习网络编程的时候&#xff0c…

甲辰年半日闲有得

甲辰年半日闲有得 出入一世红尘客&#xff0c;得失九台江湖人。 纠结苦海他日心&#xff0c;​何须挂碍当下身。 ​曾是春风得意时&#xff0c;重游故地情念真。 ​忘我才知小境遇&#xff0c;利他方明大原本。

矽塔SA8321 单通道 2.7-12.0V 持续电流 3.0A H 桥驱动芯片

描述 SA8321是为消费类产品&#xff0c;玩具和其他低压或者电池供电的运动控制类应用提供了一个集成的电机驱动器解决方案。此器件能够驱动一个直流无刷电机&#xff0c;由一个内部电荷泵生成所需的栅极驱动电压电路和4个功率 NMOS组成H桥驱动&#xff0c;集成了电机正转/反…

2024上海国际半导体制造设备材料与核心部件展览会

2024上海国际半导体制造设备材料与核心部件展览会 2024 Shanghai International Semiconductor Manufacturing Equipment Materials and Core Components Exhibition 时间&#xff1a;2024年11月18日-20日 地点&#xff1a;上海新国际博览中心 详询主办方陆先生 I38&#…

2024蓝桥杯嵌入式模板代码详解

文章目录 一、STM32CubeMx配置二、LED模板代码三、LCD模板代码 一、STM32CubeMx配置 打开STM32CubeMx&#xff0c;选择【File】->【New Project】&#xff0c;进入芯片选择界面&#xff0c;搜索到蓝桥杯官方的芯片型号&#xff0c;并点击收藏&#xff0c;下次直接点击收藏就…

【LeetCode: 39. 组合总和 + 递归】

&#x1f680; 算法题 &#x1f680; &#x1f332; 算法刷题专栏 | 面试必备算法 | 面试高频算法 &#x1f340; &#x1f332; 越难的东西,越要努力坚持&#xff0c;因为它具有很高的价值&#xff0c;算法就是这样✨ &#x1f332; 作者简介&#xff1a;硕风和炜&#xff0c;…

比特币减半倒计时:NFT 生态将受到怎样的影响?

BTC 减半倒计时仅剩不到 1 天&#xff0c;预计在 4 月 20 日迎来减半。当前区块奖励为 6.25 BTC&#xff0c;减半后区块奖励为 3.125 BTC&#xff0c;剩余区块为 253。比特币减半无疑是比特币发展史上最重要的事件之一&#xff0c;每当这一事件临近&#xff0c;整个加密社区都充…

每日三个JAVA经典面试题(四十二)

1.Java中的线程池如何帮助优化性能&#xff1f; Java中的线程池是一种重要的并发编程工具&#xff0c;它可以帮助优化性能的方式有以下几点&#xff1a; 资源管理&#xff1a;线程池可以管理并重用线程&#xff0c;而不是为每个任务都创建一个新的线程。这减少了线程创建和销毁…

Linux下SPI设备驱动实验:测试读取ICM20608设备中数据是否正常

一. 简介 前面文章实现了 SPI设备的读写功能&#xff0c;也对ICM20608设备中&#xff08;即SPI设备&#xff09;寄存器里的数据进行了读取。文章如下&#xff1a; Linux下SPI设备驱动实验&#xff1a;读取ICM20608设备的数据-CSDN博客 本文对驱动功能进行测试&#xff0c;即…

大数据平台搭建2024(二)

二&#xff1a;Hive安装 只在node01上操作 1 安装MySQL 8.0 最小化安装需要安装这个 yum install -y wget1-1 下载MySQL的yum源 wget http://dev.mysql.com/get/mysql80-community-release-el7-7.noarch.rpm检查是否安装成功 rpm -qpl mysql80-community-release-el7-7.n…

c++使用spdlog库打日记

打日记 打日志的本质就是多输出&#xff0c;c没有自带的日志库&#xff0c;只能使用第三方库实现&#xff0c;当然&#xff0c;直接cout输出也可以&#xff0c;但是一般日志库都进行了优化&#xff0c;比我们使用cout输出的效率更高&#xff0c;同时效果也更好&#xff0c;这里…

解决navicat远程连接mysql 很慢(首次)

通过navicat链接的测试服务器的mysql数据库连接打开的很慢&#xff08;间隔一段时间没使用的情况,navicat 链接会自动断开&#xff0c;再次链接就很慢&#xff0c;之后就正常&#xff0c;平时没在意&#xff0c;今天有空就给他解决下&#xff09;&#xff0c;但是连接本地的mys…

深入解析 HTML 中的 `<a>` 标签及其丰富功能

引言 HTML 中的 <a> 标签是创建超链接的关键元素之一。除了常见的超链接功能&#xff0c;<a> 标签还具有许多丰富的功能&#xff0c;使得我们可以创建交互性强、丰富多样的链接体验。本文将深入讨论 <a> 标签的功能&#xff0c;并提供相关代码示例。 1. 创…

C++:类的作用域和类的实例化

四、类的作用域 类定义了一个新的作用域&#xff0c;类的成员都在类的作用域中。在类外定义类成员需要使用&#xff1a;&#xff1a;作用域操作符指明成员属于哪个类域。 class A { public:void Print(); private:int _a;char _b; }; void A::Print()//用::指定Print属于类A …