【LeetCode】74. 搜索二维矩阵

news2024/11/24 20:30:21

74. 搜索二维矩阵(中等)

在这里插入图片描述
在这里插入图片描述在这里插入图片描述
在这里插入图片描述

方法一:二分查找

思路

  • 总体思路

    由于二维矩阵固定列的「从上到下」或者固定行的「从左到右」都是升序
    因此我们可以使用两次二分来定位到目标位置。

    1. 第一次二分: 从第 0 列中的「所有行」开始找,找到合适的行 row, 即找到最后一个满足 matrix[x][0] <= target 的行号;
    2. 第二次二分:从 row 中「所有列」开始找,找到合适的列 col ,即找到最后一个满足 matrix[row][y] <= target 的列号。
  • 二分代码解释

    这里用到了二分查找的高级模板,left = mid,用于查找数组中当前索引及其直接左邻居索引的元素或条件。

    注意,while 语句的条件是 left < right

    此外,mid 值计算需要 +1 ,如果不加 1 会出现死循环(比如l = 2, r = 3 的时候,如果不加 1,在满足 l = mid 的情况下,会一直死循环)。

    int binarySearch(vector<int>& nums, int target){
    	  if(nums.size() == 0)
    	  	return -1;
    
     	 int left = 0, right = nums.size();
      		while(left < right){
    	    // Prevent (left + right) overflow
    	    int mid = left + (right - left) / 2;
    	    if(nums[mid] == target){ return mid; }
    	    else if(nums[mid] <= target) { left = mid; }
    	    else { right = mid + 1; }
    	  }
    
    	  // Post-processing:
    	  // End Condition: left == right
    	  if(left != nums.size() && nums[right] == target) return right;
    	  return -1;
    	}
    

代码

class Solution {
public:
    bool searchMatrix(vector<vector<int>>& matrix, int target) {
        int m = matrix.size(), n = matrix[0].size();
        int row, col;
        int left = 0, right = m-1;
        // 第一次二分找到最后一个不大于目标值的元素的所在行
        while(left < right){
            int mid = left + (right - left + 1) / 2;
            if(matrix[mid][0] <= target)  left = mid;
            else right = mid - 1;
        }
        row = right;

        // 可以先判断,减少时间复杂度
        if(matrix[row][0] == target) return true;
        if(matrix[row][0] > target) return false;

        // 第二次二分找到所在列
        left = 0, right = n-1;
        while(left<right){
            int mid = left + (right - left + 1) / 2;
            if(matrix[row][mid] <= target)   left = mid;
            else right = mid - 1;
        }
        col = right;
        return matrix[row][col] == target;
    }
};

方法二:一次二分

思路

  • 如果将数组按行逐元素连接起来,那么数组将形成一个单调递增序列,我们可以使用一次二分在该 “一维数组” 中查找,如果找到target ,返回 true;否则返回false。
  • 对于一次二分,因为只有找到 target 和 没找到 target 两种情况,所以只需要普通的模板。

代码

class Solution {
public:
    bool searchMatrix(vector<vector<int>>& matrix, int target) {
        int m = matrix.size(), n = matrix[0].size();
        int left = 0, right = m * n - 1;
        // 一次二分
        while(left <= right){
            int mid = left + (right - left) / 2;
            if(matrix[mid/n][mid%n] == target) return true;
            else if(matrix[mid/n][mid%n] < target) left = mid + 1;
            else right = mid - 1;             
        }
        return false;
    }
};

方法三:抽象二叉搜索树

思路

  • 我们可以将二维矩阵抽象成「以右上角为根的 BST」:
    在这里插入图片描述

  • 那么我们可以从根(右上角)开始搜索,如果当前的节点不等于目标值,可以按照树的搜索顺序进行:

    • 当前节点「大于」目标值,搜索当前节点的「左子树」,也就是当前矩阵位置的「左方格子」,即 y–
    • 当前节点「小于」目标值,搜索当前节点的「右子树」,也就是当前矩阵位置的「下方格子」,即 x++

代码

class Solution {
public:
    bool searchMatrix(vector<vector<int>>& matrix, int target) {
        int m = matrix.size(), n = matrix[0].size();
        // 当前的坐标值,从右上角开始查找
        int x = 0, y = n-1;

        while(check(x, y, m, n) && matrix[x][y] != target){
            // 如果matrix[x][y] > target 说明需要向左查找
            if(matrix[x][y] > target)   y--;
            // 如果matrix[x][y] > target 说明需要向下查找
            else if(matrix[x][y] < target)  x++;
        }
        
        return check(x, y, m, n) && matrix[x][y] == target;
    }
    // 边界情况判断
    bool check(int x, int y, int m, int n){
        return x>=0 && x<m && y>=0 && y<n;
    }
};

参考资料

  1. 二分查找的三种模板(C++版)

  2. 【宫水三叶】一题双解:「二分」&「抽象 BST」解法

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

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

相关文章

Threejs,InstancedMesh变换操作

Threejs,InstancedMesh 在项目中加载一个道路的模型树,结果加载出来是水平的 期望是: 仔细分析: 打印模型元素,模型是两个交叉的InstancedMesh ,每个InstancedMesh 里面有566重复的mesh,形成566棵树。那么现在的期望就变成这两个交叉的InstancedMesh 各自旋转下角度 c…

高考作文题押中了?其实是一种趋势:探索、好奇、故事、技术、时间…

探索、好奇、故事、技术、时间 不知不觉&#xff0c;距离高考已经过去了23年……今年的高考题&#xff0c;关键词非常有时代感&#xff0c;不禁让人联想背后的趋势是什么&#xff1f; 趋势是无法抵挡的浪潮&#xff0c;一旦你没有跟上&#xff0c;这个时代的叙事就没有你的一份…

卡尔曼滤波与组合导航原理(二)卡尔曼滤波方程的推导

文章目录 三、卡尔曼滤波1、随机系统状态空间模型2、状态预测3、状态量测4、增益矩阵K与状态估计5、Kalman滤波公式汇总6、Kalman滤波流程图1.划分为左右两部分&#xff08;一阶矩和二阶矩&#xff09;2.划分为上下两部分&#xff08;时间更新、量测更新&#xff09; 7、Kalman…

关于如何清理过多索引的思考

今天同事提了一个问题&#xff0c;还是值得思考的&#xff0c;某个作为数据分发的MySQL库&#xff0c;有时候需要在不同的环境中同步创建数据库&#xff0c;但受工具限制&#xff0c;只能做数据同步&#xff0c;索引这些对象则需要单独创建&#xff0c;该数据库的索引太多&…

在 Transformers 中使用约束波束搜索引导文本生成

引言 本文假设读者已经熟悉文本生成领域波束搜索相关的背景知识&#xff0c;具体可参见博文 如何生成文本: 通过 Transformers 用不同的解码方法生成文本。 与普通的波束搜索不同&#xff0c;约束 波束搜索允许我们控制所生成的文本。这很有用&#xff0c;因为有时我们确切地知…

学习笔记之MySQL索引

1、引言 索引是数据库用来提高性能最常用的工具&#xff0c;一般索引本身也很大&#xff0c;不可能全部存于内存中&#xff0c;因此所以往往以文件形式存于磁盘上。 左表是数据表&#xff0c;共两列七条数据。为了加快Col2的查找&#xff0c;可以维护一个右表所示的二叉查找树…

图论与算法(7)最短路径问题

1.最短路径问题 1.1 带权图的最短路径 最短路径问题是指在一个加权图中寻找两个顶点之间的最短路径&#xff0c;其中路径的长度由边的权重确定。 常见的最短路径算法包括&#xff1a; Dijkstra算法&#xff1a;适用于解决单源最短路径问题&#xff0c;即从一个固定的起点到图…

meethigher-阿里邮箱POP3/SMTP服务

最近发现一个问题&#xff0c;小伙伴给我发的邮件&#xff0c;收和回都不及时。于是我现在将所有的邮箱&#xff0c;通过POP3/SMTP协议整合到了一起。再配合小米手环&#xff0c;就能做到邮件无遗漏。 一、邮箱常用协议 邮箱中常用三类协议 POP3 Post Office Protocol versi…

chatgpt赋能python:Python就业学历要求

Python 就业学历要求 Python 是一门广泛应用于数据科学、人工智能、Web 开发和自动化等领域的编程语言&#xff0c;正在迅速成为行业内最受欢迎的语言之一。如果你想进入这些领域从事相关职业&#xff0c;那么 Python 编程技能将是你的一个优势。但是&#xff0c;Python 就业所…

基于SSM+JSP的毕业生就业信息管理系统设计与实现

博主介绍&#xff1a; 大家好&#xff0c;我是一名在Java圈混迹十余年的程序员&#xff0c;精通Java编程语言&#xff0c;同时也熟练掌握微信小程序、Python和Android等技术&#xff0c;能够为大家提供全方位的技术支持和交流。 我擅长在JavaWeb、SSH、SSM、SpringBoot等框架下…

软考A计划-系统架构师-官方考试指定教程-(3/15)

点击跳转专栏>Unity3D特效百例点击跳转专栏>案例项目实战源码点击跳转专栏>游戏脚本-辅助自动化点击跳转专栏>Android控件全解手册点击跳转专栏>Scratch编程案例 &#x1f449;关于作者 专注于Android/Unity和各种游戏开发技巧&#xff0c;以及各种资源分享&am…

记录--纯CSS实现一个简单又不失优雅的步骤条

这里给大家分享我在网上总结出来的一些知识&#xff0c;希望对大家有所帮助 步骤条是一种用于引导用户按照特定流程完成任务的导航条&#xff0c;在各种分步表单交互场景中广泛应用。先来看一下几个主流前端 UI 框架中步骤条组件的样子&#xff1a; ElementPlus AntDesign Ope…

BCM和board的引脚的区别是什么?如何查看GPIO的BCM和board之间的关系

在树莓派(Raspberry Pi)上使用 GPIO(通用输入输出)时,引脚可以使用两种不同的编号方式:BCM(Broadcom SOC Channel)和board。 BCM 编号:BCM 编号是基于 Broadcom 芯片的引脚编号方式。它使用芯片上的引脚功能编号来标识 GPIO 引脚,这种编号方式是树莓派广泛使用的默认…

Spring事务简介及相关案例

目录 一、事务简介 二、准备数据库 三、创建maven项目&#xff0c;引入依赖和完成相关配置 1. pom.xml文件 2. 创建配置文件 四、编写Java代码 1. Account实体类 2. AccountDao接口 3. AccountService业务类 五、测试 1. 测试方法 2. 测试结果​编辑 往期专栏&…

判断数组中的每个元素是否为正无穷大或负无穷大 numpy.isinf()

【小白从小学Python、C、Java】 【计算机等级考试500强双证书】 【Python-数据分析】 判断数组中的每个元素 是否为正无穷大或负无穷大 numpy.isinf() [太阳]选择题 请问关于以下代码的最后输出的是&#xff1f; import numpy as np a np.array([-np.inf,0,np.inf]) print(&q…

chatgpt赋能python:Python实现文件复制到另一个文件夹下的方法

Python实现文件复制到另一个文件夹下的方法 如果你经常需要复制文件并将它们保存到不同的文件夹下&#xff0c;那么使用Python脚本来执行此任务是一个非常好的选择。Python提供了强大的文件操作功能&#xff0c;使得编写脚本来完成文件操作变得相对简单。在本篇文章中&#xf…

【网站 seo 排名优化】typecho Handsome 主题高排名权重优化方案

前言 前一篇优化文章主要是完成了对于 typecho 各个方面的美化与简单优化&#xff0c;如下&#xff1a; 构造你独一无二的博客美化&#xff1a;typecho joe主题优化日志 而现在博主采用的是 Handsome 主题&#xff0c;相比较 joe 主题&#xff0c;编辑、定制功能更为强大、方便…

华为OD机试真题 JavaScript 实现【合法IP】【牛客练习题】

一、题目描述 IPV4地址可以用一个32位无符号整数来表示&#xff0c;一般用点分方式来显示&#xff0c;点将IP地址分成4个部分&#xff0c;每个部分为8位&#xff0c;表示成一个无符号整数&#xff08;因此正号不需要出现&#xff09;&#xff0c;如10.137.17.1&#xff0c;是我…

Python中函数的介绍

在Python中&#xff0c;函数的三个要素是&#xff1a;函数名参数返回值 函数名&#xff1a;函数名是函数的标识符&#xff0c;用于唯一标识函数。在定义函数时&#xff0c;需要给函数一个名字&#xff0c;以便后续调用和引用。函数名应遵循命名规则&#xff0c;例如以字母或下划…

HDSLB VPP 23.04 is formally released

1 摘要 近年来随着数字化技术的发展&#xff0c;数据中心以及边缘设备的网络带宽需求越来越高。作为部署在服务入口位置的4层负载均衡器&#xff0c;其性能要求也随之水涨船高。为了应对当前的市场需求&#xff0c;充分利用Intel的软硬件技术和优势&#xff0c;针对4层负载均衡…