搜索二维矩阵——力扣74

news/2024/10/30 23:23:29/

文章目录

    • 题目描述
    • 法一)一次二分查找
    • 法二)两次二分查找
    • 法三)抽象二叉搜索树BST解法

题目描述

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

法一)一次二分查找

首先分析题目:由于①每行的整数从左到右升序;②每行的第一个整数>前一行的最后一个整数,所以,

  • 按矩阵每行拆分后,每行拼接在前一行的末尾,会得到一个升序数组
  • 在得到的数组上进行二分查找
  • 二分升序数组的下标,将其映射到矩阵的行和列上
class Solution{
public:bool searchMatrix(vector<vector<int>>& matrix, int target){int m=matrix.size(), n=matrix[0].size();   //matrix.size()表示行数  matrix[0].size()表示列数int l=0, r=m*n-1;                          //二分的是数组的下标while(l<=r){int mid=(r-l)/2 + l;int x = matrix[mid/n][mid%n];          //mid/n表示第几行,mid%n表示第几列if(x<target){l=mid+1;}else if (x>target){r=mid-1;}else{return true;}}return false;}
};

复杂度分析

  • 时间复杂度O(log mn),其中m、n分别是矩阵的行数和列数
  • 空间复杂度O(1)

法二)两次二分查找

由于①每行的第一个元素大于前一行的最后一个元素,②每行元素是升序的,所以

  • 每行的第一个元素大于前一行的第一个元素,因此矩阵第一列的元素是升序的。
  • 对矩阵的第一列的元素二分查找,找到最后一个不大于目标值的元素,然后在该元素所在行中二分查找目标值是否存在。
class Solution{
public:bool searchMatrix(vector<vector<int>>& matrix, int target){int m=matrix.size(), n=matrix[0].size();//第一次二分:定位到所在行int l=0, r=m-1;while(l<r){int mid=(l+r+1) >> 1;          //必须+1,否则容易死循环if(matrix[mid][0]<=target){l=mid;} else {r = mid-1;}}int row=r;if(matrix[r][0]==target) return true;if(matrix[r][0]>target)  return false;//第二次二分:定位所在列l=0, r=n-1;while(l<r){int mid=(l+r+1) >> 1;  if(matrix[row][mid]<=target){l=mid;}else {r=mid-1;}}int col=r;return matrix[row][col]==target;}
};

值得注意的是,二分法那里如果不加1会出现死循环,比如 l= 1, r = 2的时候,如果不加1,在满足l = mid的情况下,会一直死循环!

复杂度

  • 时间复杂度O(log mn)
  • 空间复杂度O(1)

法三)抽象二叉搜索树BST解法

将二维矩阵抽象成「以右上角为根的 BST」
在这里插入图片描述
从根(右上角)开始搜索,如果当前的节点不等于目标值,可以按照树的搜索顺序进行:

  • 当前节点「大于」目标值,搜索当前节点的「左子树」,也就是当前矩阵位置的「左方格子」,即 j–
  • 当前节点「小于」目标值,搜索当前节点的「右子树」,也就是当前矩阵位置的「下方格子」,即 i++
class Solution{
public:bool searchMatrix(vector<vector<int>>& matrix, int target){int m=matrix.size(), n=matrix[0].size();for(int i=0, j=n-1;i<m & j>=0;){if(matrix[i][j]==target)return true;else if (matrix[i][j] > target)j--;else if(matrix[i][j] < target)i++;}return false;}
};

复杂度

  • 时间复杂度O(m+n)
  • 空间复杂度O(1)

http://www.ppmy.cn/news/92232.html

相关文章

一文读懂 Java 递归,你不得不会的技能

Java递归是指在方法的执行过程中&#xff0c;通过调用自身的方式来实现重复执行一段代码的机制。它是一种非常有用的编程技术&#xff0c;特别是在处理树形数据结构或者分治算法时&#xff0c;递归能够简化代码实现&#xff0c;并使代码更易于理解和维护。 一、递归的基本原理…

2023电工杯B题全保姆教程及代码 人工智能对大学生学习影响的评价

A题&#xff1a;人工智能对大学生学习影响的评价 人工智能简称AI&#xff0c;最初由麦卡锡、明斯基等科学家于1956年在美国达特茅斯学院开会研讨时提出。2016年&#xff0c;人工智能AlphaGo 4:1战胜韩国围棋高手李世石&#xff0c;期后波士顿动力公司的人形机器人Atlas也展示了…

python+vue垃圾分类论坛的设计与实现85l30

环境保护是一项利国利民的重大民生工程,是造福子孙后代的幸福事,基于全面分析我国大学生环境保护教育现状的基础上提出了高校可通过开设环境类通识任选课、专业课中融入环境保护教育、环境保护实践教学、环境保护第二课堂等有效途径加强对非环境类专业大学生环境保护教育。 本系…

nest配置及环境变量

配置 配置问题&#xff1a; 直接使用.env文件&#xff0c;则会出现大量的process.env.xx的写法&#xff0c;且只能单独一个个获取&#xff0c;无法直接获取对象。 配置方案&#xff1a; 使用useClass 环境变量的配置在.env里面配置后&#xff0c;需要引入到config/envs内部…

如何有效地使用弹性伸缩,让云计算更高效

随着云计算的迅速发展&#xff0c;弹性伸缩作为一项重要的云服务功能&#xff0c;逐渐被越来越多的企业和开发者所关注。那么&#xff0c;什么是弹性伸缩&#xff0c;为什么它会成为标配云服务呢&#xff1f;下面将从三个方面来探讨这个问题。 一、首先&#xff0c;什么是弹性伸…

谈谈 Dapr 的优缺点,应用场景,以及未来的发展趋势,生态成熟度

谈谈 Dapr 的优缺点&#xff0c;应用场景&#xff0c;以及未来的发展趋势&#xff0c;生态成熟度 优点缺点应用场景未来发展趋势生态成熟度 本文采用 GPT4 生成&#xff0c;仅供参考。 Dapr 是一个分布式应用程序运行时&#xff0c;其目标是提供一组通用的功能&#xff0c;可以…

业务实战记录5:MySQL 字段别名导致的异常与思考

目录 引言案例分析关于字段别名的利弊结论 引言 在日常实战中&#xff0c;数据库查询是数据分析和决策过程中的关键环节。然而&#xff0c;由于现有字段和字段别名之间的冲突&#xff0c;我们可能会遇到意外的错误和困惑。因此&#xff0c;为了确保查询结果的准确性和可靠性&a…

华为OD机试真题 Java 实现【组合出合法最小数】【2023Q1 200分】

一、题目描述 给一个数组,数组里面都是代表非负整数的字符串,将数组里所有的数值排列组合拼接起来组成一个数字,输出拼接成的最小的数字。 二、输入描述 一个数组,数组不为空,数组里面都是代表非负整数的字符串,可以是0开头。 例如:[“13”, “045”, “09”, “56”…