二分算法题
文章目录
- 一、在排序数组中查找数字
- 二、0~n-1中缺失的数字
- 三、旋转数组的最小数字
- 四、二维数组中的查找
一、在排序数组中查找数字
题目传送门
法一:暴力解
直接遍历然后计数
法二:二分法求边界
看到关键字排序数组、有序数组,一定要想到二分的方法,效率高,思路也比较简单
思路:使用二分法、找数组的左边界(left)和右边界(right),最后目标数字个数就是right-left+1
对于二分法,我们可以分别求左边界和右边界,也可以二分求左边界之后接着遍历计数,两种情况对应在真实场景下连续相等的数据一般有多长。如果经常出现很长一串连续相等的数据,就用二分法求右边界,否则容易使算法退化到O(N)。PS: 在C ++11 标准中,nums.size()的时间复杂度是Constant常数级,O(1)
class Solution {
public:int search(vector<int>& nums, int target) {int res=0;int idx=getFirstIndex(nums,target);if(idx==-1) return res;for(int i=idx;i<nums.size()&&nums[i]==target;i++){res++;}return res;}int getFirstIndex(vector<int> & nums,int target){int left=0;int right=nums.size()-1;int res=-1;while(left<=right){int mid=(left+right)/2;if(nums[mid]>target){right=mid-1;}else if(nums[mid]<target){left=mid+1;}else{res=mid;right=mid-1;} }return res;}
};
标准解法:
class Solution {
public:int binarySearch(vector<int>& nums, int target, bool lower) {int left = 0, right = (int)nums.size() - 1, ans = (int)nums.size();while (left <= right) {int mid = (left + right) / 2;if (nums[mid] > target || (lower && nums[mid] >= target)) {right = mid - 1;ans = mid;} else {left = mid + 1;}}return ans;}int search(vector<int>& nums, int target) {int leftIdx = binarySearch(nums, target, true);int rightIdx = binarySearch(nums, target, false) - 1;if (leftIdx <= rightIdx && rightIdx < nums.size() && nums[leftIdx] == target && nums[rightIdx] == target) {return rightIdx - leftIdx + 1;}return 0;}
};
二、0~n-1中缺失的数字
题目传送门
思路:因为有序,所以可以看看下标是否等于数组中的对应元素
初始化: 左边界 left = 0 ,右边界 right = len(nums)−1 ;代表闭区间 [left, right] 。
循环二分: 当 left ≤ right 时循环 (即当闭区间 [left, right] 为空时跳出) ;
1、计算中点 mid = (left + right)//2 ,其中 “//” 为向下取整除法;
2、若 nums[mid] = mid ,说明mid前面的元素肯定都是完整的不少元素所以只需要继续二分右边的数组即可,则 “右子数组的首位元素” 一定在闭区间 [mid+1, right] 中,因此执行 left = mid+1;
3、若 nums[mid] != mid ,说明mid前面的元素就有少的所以只要继续二分左边的数组即可,则 “左子数组的末位元素” 一定在闭区间 [left, mid−1] 中,因此执行 right = mid−1;
4返回值: 跳出时,变量 i 和 j 分别指向 “右子数组的首元素” 和 “左子数组的末元素” 。因此返回 i 即可。

class Solution {
public:int missingNumber(vector<int>& nums) {int left=0,right=nums.size()-1;while(left<=right){int mid=(left+right)/2;if(nums[mid]==mid){left=mid+1;}else{right=mid-1;}}return left;}
};
三、旋转数组的最小数字
题目传送门
题目分析
旋转数组:把一个有重复数字的有序数组,末位一部分移动到头部,这就叫做旋转数组。在这里插入图片描述
我们的目标就是找到这个分界点!

法一:暴力
分界点右边的第一个数字就是我们要找的最小数字

其实可以类比数学中的找极点

class Solution {
public:int minArray(vector<int>& numbers) {// 注意i=0开始,要越界,特殊处理一下,从1开始可以避免for(int i=1;i<numbers.size();i++){if(numbers[i-1]>numbers[i])return numbers[i];}return numbers[0];}
};
法二:二分法
题目说了,可能存在重复的数字


---------------------===


class Solution {
public:int minArray(vector<int>& numbers) {int left=0;int right=numbers.size()-1;if(right==0) return numbers[0];while(left<right){int mid=left+(right-left)/2;if(numbers[mid]>numbers[right])left=mid+1;else if(numbers[mid]<numbers[right])right=mid;elseright--;}return numbers[left];}
};
四、二维数组中的查找
TP
法一:暴力
直接遍历矩阵,判断有没有target
class Solution {
public:bool findNumberIn2DArray(vector<vector<int>>& matrix, int target) {for(auto row: matrix){for(auto e: row){if(e==target)return true;}}return false;}
};
时间复杂度:O(MN)
空间复杂度:O(1)
法二:行二分
对二维数组每一行,进行二分查找
class Solution {
public:bool findNumberIn2DArray(vector<vector<int>>& matrix, int t) {if (matrix.size() == 0 || matrix[0].size() == 0) return false;int n = matrix.size(), m = matrix[0].size();int l = 0, r = 0, mid = 0;for (int i = 0; i < n; i ++) {l = 0;r = m - 1;while (l <= r) {mid = l + (r - l) / 2;if (matrix[i][mid] == t) return true;if (matrix[i][mid] < t) l = mid + 1;if (matrix[i][mid] > t) r = mid - 1;} }return false;}
};
时间复杂度:O(MlogN)
空间复杂度:O(1)
法三:Z字形查找

class Solution
{
public:bool findNumberIn2DArray(vector<vector<int>> &matrix, int target){int i = matrix.size() - 1; // 行int j = 0; // 列if (matrix.size() == 0 || matrix[0].size() == 0)return false;while (i >= 0 && j <= matrix[0].size() - 1){if (matrix[i][j] > target)i--;else if (matrix[i][j] < target)j++;elsereturn true;}return false;}
};
时间复杂度:O(M+N)
M,N为矩阵的行数和列数
空间复杂度:O(1)
相关文章:
二分算法题
文章目录一、在排序数组中查找数字二、0~n-1中缺失的数字三、旋转数组的最小数字四、二维数组中的查找一、在排序数组中查找数字 题目传送门 法一:暴力解 直接遍历然后计数 法二:二分法求边界 看到关键字排序数组、有序数组,一定要想到二分…...
Vue+ElementUI+SpringBoot项目配合分页插件快速实现分页(简单暴力)
首先需要在项目中引入Element-UI的组件库,使用以下命令,不会引入的请自行百度。 npm i element-ui -S Element官网地址:https://element.eleme.cn/#/zh-CN/component/changelog 去Element-UI官网组件库找到合适的分页插件,并把他引…...
【回眸】牛客网刷刷刷!嵌入式软件中也会遇到的嵌入式硬件,通讯,通讯协议专题(一)
前言 最近继续刷题,看看嵌入式软件还需要了解一些嵌入式硬件中的通讯协议和常用接口协议 比如说SPI CAN I2C 通讯协议专题 1.波特率 波特率 每秒传送的字符数 * 字符位数。串口的工作模式为1个起始位,7个数据位,1个校验位,1个…...
使用Vue展示数据(动态查询)
学习内容来源:视频P4 本篇文章进度接着之前的文章进行续写 精简前后端分离项目搭建 Vue基础容器使用 目录选择组件修改表格组件修改分页组件增加后端接口前端请求数据接口页面初始化请求数据点击页码请求数据选择组件 在官方文档中选择现成的组件,放在页…...
构建数据库测试数据——mysql
建表脚本 -- 建表 CREATE TABLE test_table (id INT(11) NOT NULL AUTO_INCREMENT,varchar_col VARCHAR(50),char_col CHAR(10),text_col TEXT,tinyint_col TINYINT(4),smallint_col SMALLINT(6),mediumint_col MEDIUMINT(9),int_col INT(11),bigint_col BIGINT(20),float_col…...
你想要的Android性能优化系列:启动优化 !
App启动优化为什么要做App的启动优化?网页端存在的一个定律叫8秒定律:即指用户访问一个网站时,如果等待打开的时间超过8秒,超过70%的用户将会放弃等待。同样的,移动端也有一个8秒定律:如果一个App的启动时间…...
python3的基础入门3:基本数据类型
基本数据类型 python 中的变量不需要声明。每个变量在使用前都必须赋值,变量赋值以后该变量才会被创建。 在 Python 中,变量就是变量,它没有类型,我们所说的"类型"是变量所指的内存中对象的类型。 等号(&…...
消息队列原理与实战-学习笔记
消息队列:保存消息的一个容器,本质是个队列,但是需要支持高吞吐、高并发、高可用。 1 前世今生 1.1 业界消息队列对比 Kafka:分布式的、分区的、多副本的日志提交服务,在高吞吐场景下发挥较为出色RocketMQ:低延迟、强一致、高性…...
Linux权限相关知识(大量图文展示,及详细操作)
Linux权限相关概念 Linux下有两种用户:一种是超级用户(root)、一种是普通用户。 超级用户:可以在linux系统下做任何事情,不受限制 普通用户:在linux下做有限的事情。 超级用户的命令提示符是“#”…...
Ep_操作系统面试题-什么是协程
协程 是一种 比线程更加轻量级的存 在,一个线程可以拥有多个协程。是一个特殊的 函数 ,这个函数可以在某个地方挂起,并且可以重新在挂起处外继续运行。协程 不是被操作系统内核所管理 , 而完全是由程序所控制(也就是在…...
在C#中使用互斥量解决多线程访问共享资源的冲突问题
在阿里云上对互斥量的概述:互斥量的获取是完全互斥的,即同一时刻,互斥量只能被一个任务获取。而信号量按照起始的计数值的配置,可以存在多个任务获取同一信号量的情况,直到计数值减为0,则后续任务无法再获取…...
JavaEE进阶第六课:SpringBoot配置文件
上篇文章介绍了SpringBoot的创建和使用,这篇文章我们将会介绍SpringBoot配置文件 目录1.配置文件的作用2.配置文件的格式2.1 .properties语法2.1.1.properties的缺点2.2 .yml语法2.2.1优点分析2.2.2配置与读取对象2.2.3配置与读取集合2.2.4补充说明3.设置不同环境的…...
MySQL基础(一)SQL分类、导入、SELECT语句,运算符
目录 MySQL安装以及相关工具 SQL分类 导入数据 最基本的SELECT语句 SELECT FROM 列的别名 去除重复行 着重号 查询常数 描述表结构 过滤数据(重要) 运算符 算数运算符 比较运算符 符号运算符 非符号运算符 逻辑运算符 位运算符 MySQL安…...
反激与正激的区别
之前学习了正激开关电源,但是对于正激和反激一直不是很清楚,网上找了一篇,觉得感觉该可以,以此记录。正激和反激是两种不同的开关电源技术一、正激(1)概述正激式开关电源是指使用正激高频变压器隔离耦合能量…...
王道操作系统课代表 - 考研计算机 第四章 文件管理 究极精华总结笔记
本篇博客是考研期间学习王道课程 传送门 的笔记,以及一整年里对 操作系统 知识点的理解的总结。希望对新一届的计算机考研人提供帮助!!! 关于对 “文件管理” 章节知识点总结的十分全面,涵括了《操作系统》课程里的全部…...
前端开发规范,你真的了解吗?一起来学习一下前端开发规范,让你的代码高级起来!
代码规范 1 编码风格规范 1.1 使用ES6风格编码源码 定义变量使用let ,定义常量使用const 使用export ,import 模块化 1.2 组件 props 原子化 提供默认值 使用 type 属性校验类型 使用 props 之前先检查该 prop 是否存在 1.3 避免 this.$parent 1.4 谨慎使用 …...
Licode—基于webrtc的SFU/MCU实现
1. webrtc浅析webrtc的前世今生、编译方法、行业应用、最佳实践等技术与产业类的文章在网上卷帙浩繁,重复的内容我不再赘述。对我来讲,webrtc的概念可以有三个角度去解释:(1).一个W3C和IETF制定的标准,约定…...
开发运维工具推荐 --- 解决远程访问局域网服务的问题。开发调试推荐
一、FastNat 可为您解决的问题1. 没公网服务器,需要发布本地的站点或网络程序到公网上,供他人访问;此项功能大大方面开发人员进行远程调试,微信小程序等开发工作进行。2. 需要远程到在其他网络中的设备,但两处的网络不…...
【华为OD机试 】单词倒序(C++ Java JS Python)
文章目录 题目描述输入描述输出描述备注用例题目解析C++ 解法JavaScript算法源码Java算法源码Python解法题目描述 输入单行英文句子,里面包含英文字母,空格以及,.?三种标点符号,请将句子内每个单词进行倒序,并输出倒序后的语句。 输入描述 输入字符串S,S的长度 1 ≤ N…...
PLC 诊断故障的基本原理
(1)东欢坨选煤厂机电设备故障信号主要取自开关量信号,PLC 通过开关量的通和断对设备进行故障诊断。PLC 对开关量的识别是通过输入模块来实现的。PLC 控制设备运行时,设备中的温度、压力、急停、跑偏、速度、过热以及各种按钮和行程开关的传感器与 PLC 输入模块相连接,输入模块的…...
MPNet:旋转机械轻量化故障诊断模型详解python代码复现
目录 一、问题背景与挑战 二、MPNet核心架构 2.1 多分支特征融合模块(MBFM) 2.2 残差注意力金字塔模块(RAPM) 2.2.1 空间金字塔注意力(SPA) 2.2.2 金字塔残差块(PRBlock) 2.3 分类器设计 三、关键技术突破 3.1 多尺度特征融合 3.2 轻量化设计策略 3.3 抗噪声…...
ssc377d修改flash分区大小
1、flash的分区默认分配16M、 / # df -h Filesystem Size Used Available Use% Mounted on /dev/root 1.9M 1.9M 0 100% / /dev/mtdblock4 3.0M...
线程同步:确保多线程程序的安全与高效!
全文目录: 开篇语前序前言第一部分:线程同步的概念与问题1.1 线程同步的概念1.2 线程同步的问题1.3 线程同步的解决方案 第二部分:synchronized关键字的使用2.1 使用 synchronized修饰方法2.2 使用 synchronized修饰代码块 第三部分ÿ…...
dify打造数据可视化图表
一、概述 在日常工作和学习中,我们经常需要和数据打交道。无论是分析报告、项目展示,还是简单的数据洞察,一个清晰直观的图表,往往能胜过千言万语。 一款能让数据可视化变得超级简单的 MCP Server,由蚂蚁集团 AntV 团队…...
面向无人机海岸带生态系统监测的语义分割基准数据集
描述:海岸带生态系统的监测是维护生态平衡和可持续发展的重要任务。语义分割技术在遥感影像中的应用为海岸带生态系统的精准监测提供了有效手段。然而,目前该领域仍面临一个挑战,即缺乏公开的专门面向海岸带生态系统的语义分割基准数据集。受…...
人机融合智能 | “人智交互”跨学科新领域
本文系统地提出基于“以人为中心AI(HCAI)”理念的人-人工智能交互(人智交互)这一跨学科新领域及框架,定义人智交互领域的理念、基本理论和关键问题、方法、开发流程和参与团队等,阐述提出人智交互新领域的意义。然后,提出人智交互研究的三种新范式取向以及它们的意义。最后,总结…...
GitFlow 工作模式(详解)
今天再学项目的过程中遇到使用gitflow模式管理代码,因此进行学习并且发布关于gitflow的一些思考 Git与GitFlow模式 我们在写代码的时候通常会进行网上保存,无论是github还是gittee,都是一种基于git去保存代码的形式,这样保存代码…...
LLMs 系列实操科普(1)
写在前面: 本期内容我们继续 Andrej Karpathy 的《How I use LLMs》讲座内容,原视频时长 ~130 分钟,以实操演示主流的一些 LLMs 的使用,由于涉及到实操,实际上并不适合以文字整理,但还是决定尽量整理一份笔…...
LRU 缓存机制详解与实现(Java版) + 力扣解决
📌 LRU 缓存机制详解与实现(Java版) 一、📖 问题背景 在日常开发中,我们经常会使用 缓存(Cache) 来提升性能。但由于内存有限,缓存不可能无限增长,于是需要策略决定&am…...
Git 3天2K星标:Datawhale 的 Happy-LLM 项目介绍(附教程)
引言 在人工智能飞速发展的今天,大语言模型(Large Language Models, LLMs)已成为技术领域的焦点。从智能写作到代码生成,LLM 的应用场景不断扩展,深刻改变了我们的工作和生活方式。然而,理解这些模型的内部…...
