力扣 搜索二维矩阵

news2025/1/21 23:38:52

二分查找,闭区间与开区间的不同解法。

题目

乍一看,不是遍历一下找到元素就可以了。

class Solution {
    public boolean searchMatrix(int[][] matrix, int target) {

        for (int[] ints : matrix) {
            for (int ans : ints) {
                if (ans == target) return true;
            }
        }
        
        return false;

    }
}

可以通过的,但还是可以优化一下的。这题可以用二分的思路,可以把整个矩阵看成一大个数组,若将矩阵每一行拼接在上一行的末尾,则会得到一个升序数组,我们可以在该数组上二分找到目标元素。但是这种方法在每一行元素个数不一时会失效。

时间复杂度:O(logmn),空间复杂度:O(1)。

class Solution {
    public boolean searchMatrix(int[][] matrix, int target) {
        int m = matrix.length, n = matrix[0].length;
        int low = 0, high = m * n - 1;
        while (low <= high) {
            int mid = (high - low) / 2 + low;
            int x = matrix[mid / n][mid % n];
            if (x < target) {
                low = mid + 1;
            } else if (x > target) {
                high = mid - 1;
            } else {
                return true;
            }
        }
        return false;
    }
}

以上为标准二分查找的写法,其中首尾做为边界,条件时while (low <= high),接着如果目标值偏大则在右边找,即low = mid + 1,反之,目标值偏小时往左边找,即 high = mid - 1,然后当low指针从左边到target时扫了一遍,当high指针从右边到target时扫了一遍,当两个指针重叠相遇时,进一步判断两个指针定住的数是不是目标数,然后退出循环。

这题还可以先对行二分,再对列二分,进行两次二分查找。每行的第一个元素大于前一行的第一个元素,矩阵第一列的元素是升序的。对矩阵的第一列的元素二分查找,找到最后一个不大于目标值的元素,然后在该元素所在行中二分查找目标值是否存在。

时间复杂度:O(logmn),空间复杂度:O(1)。

class Solution {
    public boolean searchMatrix(int[][] matrix, int target) {
        int rowIndex = binarySearchFirstColumn(matrix, target);
        if (rowIndex < 0) {
            return false;
        }
        return binarySearchRow(matrix[rowIndex], target);
    }

    public int binarySearchFirstColumn(int[][] matrix, int target) {
        int low = -1, high = matrix.length - 1;
        while (low < high) {
            int mid = (high - low + 1) / 2 + low;
            if (matrix[mid][0] <= target) {
                low = mid;
            } else {
                high = mid - 1;
            }
        }
        return low;
    }

    public boolean binarySearchRow(int[] row, int target) {
        int low = 0, high = row.length - 1;
        while (low <= high) {
            int mid = (high - low) / 2 + low;
            if (row[mid] == target) {
                return true;
            } else if (row[mid] > target) {
                high = mid - 1;
            } else {
                low = mid + 1;
            }
        }
        return false;
    }
}

其中,用了一个左开右闭区间的二分查找,可以先进行扩充边界,然后条件改为while (low < high),接着low要设置为mid,退出的条件即当low跟high重叠时,此时的low是mid了,看是不是要找的target。当然,这题用左闭右开区间的二分查找也是类似,不过要注意以下返回值,要取到不大于目标值的最大行索引。

class Solution {
    public boolean searchMatrix(int[][] matrix, int target) {
        int rowIndex = binarySearchFirstColumn(matrix, target);
        if (rowIndex < 0) {
            return false;
        }
        return binarySearchRow(matrix[rowIndex], target);
    }
public int binarySearchFirstColumn(int[][] matrix, int target) {
    int low = 0, high = matrix.length;  
    while (low < high) {  
        int mid = (high - low) / 2 + low;  
        if (matrix[mid][0] <= target) {  
            low = mid + 1;
        } else {  
            high = mid;  
        }
    }
    return high-1; 
}
    public boolean binarySearchRow(int[] row, int target) {
        int low = 0, high = row.length - 1;
        while (low <= high) {
            int mid = (high - low) / 2 + low;
            if (row[mid] == target) {
                return true;
            } else if (row[mid] > target) {
                high = mid - 1;
            } else {
                low = mid + 1;
            }
        }
        return false;
    }
}

然后,也可以用最经典的标准二分模板去写。

class Solution {
    public boolean searchMatrix(int[][] matrix, int target) {
        int rowIndex = binarySearchFirstColumn(matrix, target);
        if (rowIndex < 0) {
            return false;
        }
        return binarySearchRow(matrix[rowIndex], target);
    }
public int binarySearchFirstColumn(int[][] matrix, int target) {
    // 初始化low为0,high为矩阵最后一行的索引
    int low = 0, high = matrix.length - 1;
    while (low <= high) {  // 当low不大于high时继续循环
        int mid = (high - low) / 2 + low;  // 计算中间位置
        // 如果中间位置的行的第一个元素小于或等于目标值,则该行及之后的行可能是候选行
        if (matrix[mid][0] <= target) {
            low = mid + 1;  
        } else {
            high = mid - 1; 
        }
    }
    // 返回不大于目标值的最大行索引
    return high;  // 这里返回high,因为high指向的是不大于目标值的最大行索引或未找到返回-1
    
  
}
    public boolean binarySearchRow(int[] row, int target) {
        int low = 0, high = row.length - 1;
        while (low <= high) {
            int mid = (high - low) / 2 + low;
            if (row[mid] == target) {
                return true;
            } else if (row[mid] > target) {
                high = mid - 1;
            } else {
                low = mid + 1;
            }
        }
        return false;
    }
}

二分查找模板巧记,先写好数组中的左右边界值,然后while (low <= high),接着写mid的求值 int mid = (high - low) / 2 + low,再到判断,若目标值偏大往大的找即low指针右移,若目标值偏小往小的找即high指针左移,最后当low跟high重叠时对当前元素做判断,返回值依题而定。

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

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

相关文章

Linux 使用 GDB 进行调试的常用命令与技巧

GDB 调试的常用命令与技巧 1. GDB 常用命令1.1 安装 GDB1.2 启动 GDB1.3 设置程序的参数1.4 设置断点1.5 启动程序并运行至断点1.6 执行一步1.7 打印变量值1.8 查看函数调用栈 2. GDB 调试 Core 文件2.1 生成 Core 文件2.2 使用 GDB 调试 Core 文件 3. GDB 调试正在运行的程序3…

微服务网关,如何选择?

什么是API网关 API网关&#xff08;API Gateway&#xff09;是微服务架构中的一个关键组件&#xff0c;它充当了客户端与后端服务之间的中间层。其主要功能包括请求路由、协议转换、负载均衡、安全认证、限流熔断等。通过API网关&#xff0c;客户端无需直接与多个微服务交互&a…

Spring 6 第3章——容器:IoC

一、IoC容器 IoC是Inversion of Control的简写&#xff0c;翻译为“控制反转”.它不是一门技术&#xff0c;而是一种设计思想 Spring通过IoC容器来管理&#xff08;1&#xff09;所有Java对象的实例化和初始化&#xff0c;&#xff08;2&#xff09;控制对象与对象之间的依赖…

Docker:基于自制openjdk8镜像 or 官方openjdk8镜像,制作tomcat镜像

一、制作openjdk8基础镜像【基于自定义alpine-3.18.0:v1 】 docker pull maven:3.5.0-jdk-8-alpine 78.56 MB https://hub.docker.com/_/maven/tagspage8&namealpine openjdk二进制下载地址 https://blog.csdn.net/fenglllle/article/details/124786948 https://adoptope…

数据结构漫游记:动态实现栈(stack)

嘿&#xff0c;各位技术潮人&#xff01;好久不见甚是想念。生活就像一场奇妙冒险&#xff0c;而编程就是那把超酷的万能钥匙。此刻&#xff0c;阳光洒在键盘上&#xff0c;灵感在指尖跳跃&#xff0c;让我们抛开一切束缚&#xff0c;给平淡日子加点料&#xff0c;注入满满的pa…

鸿蒙系统 将工程HarmonyOS变成OpenHarmony

DevEco Studio软件创建工程后需要修改两个地方&#xff1a; 修改第二个build-profile.json5文件 将原先内容&#xff1a; {"app": {"signingConfigs": [],"products": [{"name": "default","signingConfig": &q…

MySQL 事务及MVCC机制详解

目录 什么是事务 事务的隔离级别 数据库并发的三种场景 读-写 什么是事务 事务就是一组DML语句组成&#xff0c;这些语句在逻辑上存在相关性&#xff0c;这一组DML语句要么全部成功&#xff0c;要么全部失败&#xff0c;是一个整体。MySQL提供一种机制&#xff0c;保证我们…

将 AzureBlob 的日志通过 Azure Event Hubs 发给 Elasticsearch(3.纯python的实惠版)

前情&#xff1a; 将 AzureBlob 的日志通过 Azure Event Hubs 发给 Elasticsearch&#xff08;1.标准版&#xff09;-CSDN博客 将 AzureBlob 的日志通过 Azure Event Hubs 发给 Elasticsearch&#xff08;2.换掉付费的Event Hubs&#xff09;-CSDN博客 python脚本实现 厉害的…

什么是三高架构?

大家好&#xff0c;我是锋哥。今天分享关于【什么是三高架构?】面试题。希望对大家有帮助&#xff1b; 什么是三高架构? 1000道 互联网大厂Java工程师 精选面试题-Java资源分享网 “三高架构”通常是指高可用性&#xff08;High Availability&#xff09;、高性能&#xff…

[微服务]注册中心优化

环境隔离 企业实际开发中&#xff0c;往往会搭建多个运行环境&#xff0c;例如&#xff1a; 开发环境测试环境预发布环境生产环境 这些不同环境之间的服务和数据之间需要隔离。 还有的企业中&#xff0c;会开发多个项目&#xff0c;共享nacos集群。此时&#xff0c;这些项目…

uniapp——App 监听下载文件状态,打开文件(三)

5 实现下载文件并打开 这里演示&#xff0c;导出Excel 表格 文章目录 5 实现下载文件并打开DEMO监听下载进度效果图为什么 totalSize 一直为0&#xff1f; 相关Api&#xff1a; downloader DEMO 提示&#xff1a; 请求方式支持&#xff1a;GET、POST&#xff1b;POST 方式需要…

地图:nuxt3高德地图简单使用 / nuxt2 + amap

一、官方网站 JS API 安全密钥使用-基础-进阶教程-地图 JS API 2.0 | 高德地图API 二、使用 2.1、创建应用 2.2、添加key&#xff0c;得到key值 2.3、nuxt3项目 引入amap 2.4、pages/map.vue <template><div class"container"><div id"map-co…

Java面试专题——面向对象

面向过程和面向对象的区别 面向过程&#xff1a;当事件比较简单的时候&#xff0c;利用面向过程&#xff0c;注重的是事件的具体的步骤/过程&#xff0c;注重的是过程中的具体的行为&#xff0c;以函数为最小单位&#xff0c;考虑怎么做。 面向对象&#xff1a;注重找“参与者…

Flowable 管理各业务流程:流程设计器 (获取流程模型 XML)、流程部署、启动流程、流程审批、流程挂起和激活、任务分配

文章目录 引言I 表结构主要表前缀及其用途核心表II 流程设计器(Flowable BPMN模型编辑器插件)Flowable-UIvue插件III 流程部署部署步骤例子:根据流程模型ID部署IV 启动流程启动步骤ACT_RE_PROCDEF:流程定义相关信息例子:根据流程 ID 启动流程V 流程审批审批步骤Flowable 审…

VIVADO ILA IP进阶使用之任意设置ILA的采样频率

VIVADO ILA IP进阶使用之任意设置ILA的采样频率 VIVADO ILA IP和VIO IP结合使用任意设置ILA的采样频率 目录 前言 一、VIO IP的配置 二、ILA IP的配置 三、测试代码 四、测试结果 总结 前言 VIVADO中编写完程序上板测试时经常会用到viavdo自带的ILA逻辑分析仪IP核&#x…

【机器学习实战入门】使用LSTM机器学习预测股票价格

机器学习在股票价格预测中有重要的应用。在这个机器学习项目中&#xff0c;我们将讨论如何预测股票的收益。这是一个非常复杂的任务&#xff0c;充满了不确定性。我们将会把这个项目分成两部分进行开发&#xff1a; 首先&#xff0c;我们将学习如何使用 LSTM 神经网络预测股票…

DilateFormer: Multi-Scale Dilated Transformer for Visual Recognition 中的空洞自注意力机制

空洞自注意力机制 文章目录 摘要1. 模型解释1.1. 滑动窗口扩张注意力1.2. 多尺度扩张注意力 2. 代码3. 流程图3.1. MultiDilatelocalAttention3.2. DilateAttention3.3. MLP 摘要 本文针对DilateFormer中的空洞自注意力机制原理和代码进行详细介绍&#xff0c;最后通过流程图梳…

大模型GUI系列论文阅读 DAY2续:《一个具备规划、长上下文理解和程序合成能力的真实世界Web代理》

摘要 预训练的大语言模型&#xff08;LLMs&#xff09;近年来在自主网页自动化方面实现了更好的泛化能力和样本效率。然而&#xff0c;在真实世界的网站上&#xff0c;其性能仍然受到以下问题的影响&#xff1a;(1) 开放领域的复杂性&#xff0c;(2) 有限的上下文长度&#xff…

Qt按钮美化教程

前言 Qt按钮美化主要有三种方式&#xff1a;QSS、属性和自绘 QSS 字体大小 font-size: 18px;文字颜色 color: white;背景颜色 background-color: rgb(10,88,163); 按钮边框 border: 2px solid rgb(114,188,51);文字对齐 text-align: left;左侧内边距 padding-left: 10…

云IDE:开启软件开发的未来篇章

敖行客一直致力于将整个研发协作流程线上化&#xff0c;从而打破物理环境依赖&#xff0c;让研发组织模式更加灵活、自由且高效&#xff0c;今天就来聊聊AT Work&#xff08;一站式研发协作平台&#xff09;的重要组成部分-云IDE。 在科技领域&#xff0c;历史常常是未来的风向…