当前位置: 首页 > news >正文

LeetCode 热题 100_搜索二维矩阵(64_74_中等_C++)(二分查找)(暴力破解法;Z字形查找;一次二分查找)

LeetCode 热题 100_搜索二维矩阵(64_74)

    • 题目描述:
    • 输入输出样例:
    • 题解:
      • 解题思路:
        • 思路一(暴力破解法):
        • 思路二(Z字形查找):
        • 思路三(一次二分查找(将二维转换为一维)):
      • 代码实现
        • 代码实现(思路一(暴力破解法)):
        • 代码实现(思路二(Z字形查找)):
        • 代码实现(思路三(一次二分查找(将二维转换为一维))):
        • 以思路三为例进行调试
        • 部分代码解读

题目描述:

给你一个满足下述两条属性的 m x n 整数矩阵:

每行中的整数从左到右按非严格递增顺序排列。
每行的第一个整数大于前一行的最后一个整数。
给你一个整数 target ,如果 target 在矩阵中,返回 true ;否则,返回 false 。

输入输出样例:

示例 1:
在这里插入图片描述

输入:matrix = [[1,3,5,7],[10,11,16,20],[23,30,34,60]], target = 3
输出:true

示例 2:
在这里插入图片描述

输入:matrix = [[1,3,5,7],[10,11,16,20],[23,30,34,60]], target = 13
输出:false

提示:
m== matrix.length
n == matrix[i].length
1 <= m, n <= 100
-104 <= matrix[i][j], target <= 104

题解:

解题思路:

思路一(暴力破解法):

1、将二维矩阵每个元素与target进行比较。
2、复杂度分析:
① 时间复杂度:O(mn),其中m和n分别是矩阵的行数和列数。
② 空间复杂度:O(1)。

思路二(Z字形查找):

1、选取划分的区间:
① 发现右上角元素的左侧是比其小的元素,下方是比其大的元素(仅看当前元素所在的行和列)。
② 发现左下角元素的上侧是比其小的元素,右侧是比其大的元素(仅看当前元素所在的行和列)。
③ 而左上角和右下角则不能划分大小区间
选择以左下角元素为基准元素,(也可选右上角元素为基准元素)
相似题目(讲解更详细):
LeetCode 热题 100_搜索二维矩阵 II(21_240_中等_C++)(Z 字形查找)

2、复杂度分析
① 时间复杂度:O(m+n),其中m和n分别为矩阵行数和列数,此算法最多循环 m+n 次。
② 空间复杂度:O(1)。

思路三(一次二分查找(将二维转换为一维)):

1、将二维数组看作是一维数组进行处理(运用“%”映射到一维)。
例:
在这里插入图片描述
按照一维数组空间展开为:[1,3,5,7,10,11,16,20,23,30,34,60]
一维:中间元素取11,其下标为 5
二维:中间元素取11,其下标为 [1,1]
5/3(column_size)=1(行)
5%4(column_size)=1(列)
一维和二维的对应关系为:
一维元素的下标 / 矩阵列数 = 二维元素的行下标
一维元素的下标 % 矩阵列数 = 二维元素的列下标

2、复杂度分析:
① 时间复杂度:O(logmn),其中m和n分别是矩阵的行数和列数。
② 空间复杂度:O(1)。

代码实现

代码实现(思路一(暴力破解法)):
bool searchMatrix1(vector<vector<int>>& matrix, int target) {
    for (int row = 0; row < matrix.size(); row++)
    {
        for (int col = 0; col < matrix[0].size(); col++)
        {
            if(matrix[row][col]==target){
                return true;
            }
        }
    }
    return false;
}
代码实现(思路二(Z字形查找)):
bool searchMatrix2(vector<vector<int>>& matrix, int target) {
    // 初始化row为矩阵的最后一行,col为矩阵的第一列(左下角元素)
    int row = matrix.size() - 1;
    int col = 0;

    // 循环直到超出矩阵边界
    while (row >= 0 && col < matrix[0].size()) {
        // 如果当前元素等于目标值,返回true
        if (matrix[row][col] == target) {
            return true;
        }
        // 如果当前元素大于目标值,说明目标值在当前行的上方,向上移动一行
        else if (matrix[row][col] > target) {
            --row;
        }
        // 如果当前元素小于目标值,说明目标值在当前列的右侧,向右移动一列
        else {
            ++col;
        }
    }
    // 如果没有找到目标值,返回false
    return false;
}
代码实现(思路三(一次二分查找(将二维转换为一维))):
//方法三:一次二分查找
bool searchMatrix3(vector<vector<int>>& matrix, int target) {
    // 获取二维数组的行数和列数
    int row_size = matrix.size(), col_size = matrix[0].size();
    
    // 初始化二分查找的左边界和右边界
    // 通过将二维矩阵转换成一维数组来处理
    int left = 0, right = row_size * col_size - 1, mid;

    // 当左边界不超过右边界时,继续进行二分查找
    while (left <= right) {
        // 计算中间索引 mid,使用位移操作 >>1 代替除以2,提高效率
        mid = left + ((right - left) >> 1);
        
        // 将中间索引对应到二维矩阵中的位置,mid / col_size 为行,mid % col_size 为列
        int x = matrix[mid / col_size][mid % col_size];
        
        // 如果目标值小于当前值,移动右边界
        if (x > target) {
            right = mid - 1;
        }
        // 如果目标值大于当前值,移动左边界
        else if (x < target) {
            left = mid + 1;
        }
        // 找到目标值,返回 true
        else {
            return true;
        }
    }
    // 如果未找到目标值,返回 false
    return false;
}
以思路三为例进行调试
#include<iostream>
#include<vector>
using namespace std;

class Solution {
public:
    //方法三:一次二分查找
    bool searchMatrix3(vector<vector<int>>& matrix, int target) {
        // 获取二维数组的行数和列数
        int row_size = matrix.size(), col_size = matrix[0].size();
        
        // 初始化二分查找的左边界和右边界
        // 通过将二维矩阵转换成一维数组来处理
        int left = 0, right = row_size * col_size - 1, mid;

        // 当左边界不超过右边界时,继续进行二分查找
        while (left <= right) {
            // 计算中间索引 mid,使用位移操作 >>1 代替除以2,提高效率
            mid = left + ((right - left) >> 1);
            
            // 将中间索引对应到二维矩阵中的位置,mid / col_size 为行,mid % col_size 为列
            int x = matrix[mid / col_size][mid % col_size];
            
            // 如果目标值小于当前值,移动右边界
            if (x > target) {
                right = mid - 1;
            }
            // 如果目标值大于当前值,移动左边界
            else if (x < target) {
                left = mid + 1;
            }
            // 找到目标值,返回 true
            else {
                return true;
            }
        }
        // 如果未找到目标值,返回 false
        return false;
    }

};

int main(){
    vector<vector<int>> matrix={{1,3,5,7},{10,11,16,20},{23,30,34,60}};
    int target=3;

    Solution s;
    if (s.searchMatrix3(matrix,target))
    {
        cout<<"true";
    }else{
        cout<<"false";
    }
    
    return 0;
}
部分代码解读

”>>“ 与 “/” 对比 :LeetCode 热题 100_搜索插入位置(63_35_简单_C++):请点击此链接查看部分代码解读部分

LeetCode 热题 100_搜索二维矩阵(64_74)原题链接
欢迎大家和我沟通交流(✿◠‿◠)

http://www.dtcms.com/a/30906.html

相关文章:

  • 第8章:LangChain检索增强生成RAG--2.4Advanced RAG【高级RAG】
  • windows怎样查看系统信息(处理器等)
  • QSplashScreen --软件启动前的交互
  • 头像壁纸小程序源码,壁纸取图小程序源码系统
  • 【matlab代码】基于故障概率加权与多模态滤波的AUV多源融合导航
  • 如何有效利用MYSQL的连接数
  • cline通过硅基流动平台接入DeepSeek-R1模型接入指南
  • Windows 下如何对 node/vue 进行多版本管理?
  • 【后端基础】布隆过滤器原理
  • flowable适配达梦数据库
  • 二叉树的前序、中序、后序遍历(递归和非递归实现)
  • SpringBoot 自动装配原理详解
  • [答疑]领域建模:邓丽君、周杰伦和少女时代
  • 矩阵-旋转图像
  • Web - JS基础语法与表达式
  • 手机怎样玩电脑游戏?
  • OSPF基础知识总结
  • Nginx学习笔记:常用命令端口占用报错解决Nginx核心配置文件解读
  • Linux 安装 Nginx
  • 开源一款I2C电机驱动扩展板-FreakStudio多米诺系列
  • 20250221 NLP
  • Selenium实战案例1:论文pdf自动下载
  • 体育电竞比分网开发流程
  • 内容中台驱动企业智能运营升级
  • Java多线程深度解析
  • 【总结】GraphRAG与传统RAG的深度对比及主流项目分析
  • 麒麟v10 飞腾架构 配置Qt编译环境
  • Hive Orc表数据导出和导入
  • DEMF模型赋能多模态图像融合,助力肺癌高效分类
  • 以太网的PHY(物理层)详解