C++ 之二分查找(指定数、左边界、右边界)模板

【入门】二分查找左侧边界 题目描述请在一个有序不递减的数组中(数组中有相等的值),采用二分查找,找到值x第1次出现的位置,如果不存在x请输出-1。请注意:本题要求出q个x,每个x在数组中第一次出现的位置。比如有6个数,分别是:1 2 2 2 3 3,那么如果要求3个数:3 2 5,在数组中第一次出现的位置,答案是:5 2 -1。输入第一行,一个整数n,代表数组元素个数(n ... 阅读详情

C++ 之二分查找(指定数、左边界、右边界)模板

1. 查找指定数

int findTarget(vector<int>& nums, int target) {
	int left = 0, right = nums.size() - 1;

	while (left <= right) {
		int mid = left + right >> 1;

		if (nums[mid] == target) {
			return mid;
		}
		else if (nums[mid] < target) {
			left = mid + 1;
		}
		else {
			right = mid - 1;
		}
	}

	return -1;
}

2. 查找指定数的右边界(最右边等于指定数的坐标)

int rightBound(vector<int>& nums, int target) {
	int left = 0, right = nums.size() - 1;  //Q1

	while (left <= right) {   //Q2
		int mid = left + right >> 1;
 		if (nums[mid] == target) {
			left = mid + 1;   //Q3
		}
		else if (nums[mid] < target) {
			left = mid + 1;  //Q3
		}
		else {
			right = mid - 1;  //Q5
		}
	}

	if (right < 0 ) return -1;  //Q6
	return right;   //Q7 Q8
}

2.1 详细分析每一步

Q1: 为什么右边界 right 要等于 nums.size() - 1?
A1: 我们每次左闭右闭的区间内搜索。

Q2: 为什么循环条件是 “left <= right”?
A2: 因为在左闭右闭的区间内搜索,最后一次搜索满足 “left = right”,此时搜索的区间是 [left, left] (或者表示为 [right, right])仍然是有效区间。在最后一次搜索结束后,新一轮不满足循环条件的终止条件是 [left + 1, left] (或者表示为 [right + 1, right])不是有效区间,因此应该退出了。

Q3: 为什么 “nums[mid] == target” 时 “left = mid + 1”?
A3: 因为是寻找右边界,所以即使和搜索值相等,也要不断的增加左边界的坐标来缩小区间(左边界向右移动)。

Q4:为什么 “nums[mid] < target” 时 “left = mid + 1”?
A4: 当 “nums[mid]”都比你要找的指定数小了,你觉得指定数的右边界还会在 [left, mid - 1] 里面吗?

Q5: 为什么 “nums[mid] > target” 时 “right = mid - 1”?
A5: 因为 “nums[mid]”比你要找的指定数大,所以指定数只可能会出现在[left, mid - 1]之间,所以下次搜索将righ 置为 “mid - 1”。

Q6: if (right < 0 ) return -1 是干嘛用的?
A6: 假设要搜索的数组为 [1,2,3],你指定数为-1,那-1的右边界是谁?最后返回的right究竟细节是怎么样的?
因为-1在边界之外,所以在缩小区间的过程中只有一种可能,那就是右边界不断的缩小,缩到 left = right = mid = 0的时候是最后一次搜索。在最后一次搜索时,由于nums[mid] < target,因此 right = mid - 1(变成-1),此时已经是无效的坐标了。因此 “if (right < 0 ) return -1” 就是来解决这种情况的。

Q7: 指定数大于数组最大值怎么办?比如 nums = [1, 2, 3, 3, 5], target = 6?
A7: 最后返回的right究竟细节是怎么样的?
因为6在边界之外,所以在缩小区间的过程中只有一种可能,那就是左边界不断的缩小,缩到 left = right = mid = 4的时候是最后一次搜索。在最后一次搜索时,由于nums[mid] < target,因此 left = mid + 1(变成5),此时已经是无效的坐标了, 此时跳出循环是“left = 5, right = 4”。因此 “指定数大于数组最大值时”,返回是最后一个坐标。

Q8: 指定数不在数组内怎么办?比如 nums = [1, 2, 3, 3, 5], target = 4?
A8: 先问你 nums = [1, 2, 3, 3], target = 4 时最后返回的right究竟细节是怎么样的?这样问题就回到Q7,答案就是right指向最后一个坐标 right = 3。
在加上5之后,答案也是一样的,因为5都没有影响边界的缩小情况。所以“指定数不在数组内时”,指向第一个小于target的坐标。

3. 查找指定数的左边界(最左边等于指定数的坐标)

int leftBound(vector<int>& nums, int target) {
	int left = 0, right = nums.size() - 1;

	while (left <= right) {
		int mid = left + right >> 1;

		if (nums[mid] == target) {
			right = mid - 1;
		}
		else if (nums[mid] < target) {
			left = mid + 1;
		}
		else {
			right = mid - 1;
		}
	}

	if (left == nums.size()) return -1;
	return left;
}

左右边界的问题是对称的,这里不再赘述。

4. 三个问题统一模板

int findIndex(vector<int>& nums, int target) {
	int left = 0, right = nums.size() - 1;

	while (left <= right) {
		int mid = left + right >> 1;
		if (nums[mid] == target) {
			 return mid;  			1. 查找指定数 
			 //right = mid - 1;  		2. 查找左边界
			 //left = mid + 1; 		3. 查找右边界
		}
		else if (nums[mid] < target) {
			left = mid + 1;
		}
		else {
			right = mid - 1;
		}
	}

	return -1;  								1. 查找指定数 
	//return left == num.size() ? - 1 : left; 	2. 查找左边界
	//return right == -1 ? -1 : right; 			3. 查找右边界
}
【入门】二分查找右侧边界 题目描述请在一个有序不递减的数组中(数组中的值有相等的值),采用二分查找,找到最后1次出现值x的位置,如果不存在x请输出-1。请注意:本题要求出q个x,每个x在数组中第一次出现的位置。比如有6个数,分别是:1 2 2 2 3 3,那么如果要求3个数:3 2 5,在数组中最后一次出现的位置,答案是:6 4 -1。输入第一行,一个整数n,代表数组元素个数(n ... 阅读详情

相关推荐

问题 E: 起止位置(C++)(二分查找)

王老师想要查询,年龄为x的同学,在队伍中首次出现的位置和最后一次出现的位置;如果队伍中不存在年龄为x的同学,请输出-1。请注意:本题中王老师查询年龄x出现的起止位置,并不是查询了1次,而是查询了q次。共q行,每行包含两个整数,表示所求年龄在队伍中的起始位置和终止位置。年龄为8的同学首次和最后一次出现的位置分别是:-1 -1;年龄为2的同学首次和最后一次出现的位置分别是:2 4;年龄为1的同学首次和最后一次出现的位置分别是:1 1;年龄为3的同学首次和最后一次出现的位置分别是:5 6;

m0_73795998的博客 2594

【C++二分查找详解】基本二分、左右边界问题集合

一、寻找一个数(基本二分查找) 1、题目描述 给定单调不减有序数组 nums ,寻找 target 是否在数组中,若找到返回其下标,否则返回-1。 2、代码框架 /*基本二分*/ int binarySearch(vector<int>& nums,int target) { int left=0,right=nums.size()-1; int mid; while(left<=right) { mid...

saxon_li的博客 2962

别再暴力搜索了!用C++ STL的binary_search函数5分钟搞定‘两数之和’问题(附NOI真题解析)

本文介绍如何利用C++ STL中的binary_search函数高效解决‘两数之和’问题,避免暴力搜索的低效和手写二分查找的复杂性。通过NOI真题解析,展示排序后使用binary_search的简洁实现,提升算法效率和代码可读性,适用于算法竞赛和面试准备。

weixin_30819085的博客 878

算法刷题:二分查找及对应左边界和右边界的寻找整理

算法刷题关于二分查找部分的知识整理

qjyws的博客 3152

HAUT2021蓝桥杯专题练习第三周记录——二分+前缀和+双指针

HAUT2021蓝桥杯专题练习第二周记录——搜索 这周因为迷迷糊糊的早早的写完了,然后玩了好几天基本上题都忘完了才写的博客,基本上啥都不记得了QAQ 说迷迷糊糊是因为这周确实太懵了,精度问题,还有我原本就不太会的前缀和,然后力扣这个月又是滑窗月,每日都很头疼。 不过,总算是跟着题解做完了 题目列表HAUT2021蓝桥杯专题练习第二周记录——搜索A 二分查找(一)(计蒜客T1560)B 二分查找(三)(计蒜客T1562)C 二分查找(六)(计蒜客T1556)D 和为给定数(计蒜客T1158)E 一元三次方程求

qq_39549803的博客 538

服务器被矿工入侵记录

一次服务器被矿工入驻的处理记录

王瑞的技术专栏 1333

信息学奥赛解题精讲:二分查找实战之“和为给定数” | OpenJudge NOI 1.11 07

本文深入解析信息学奥赛中二分查找算法的实战应用,以OpenJudge NOI 1.11 07题'和为给定数'为例,详细讲解手写二分查找与STL实现的技巧与优化策略。通过算法设计、代码实现和复杂度分析,帮助竞赛选手掌握这一高效查找技术,提升解题效率。

weixin_33739627的博客 259

基于STM32F407与AD9910/AD9959的高频可调DDS信号源设计与实战

本文详细介绍了基于STM32F407微控制器与AD9910/AD9959高性能DDS芯片的高频可调信号源设计与实现。文章从DDS原理入手,阐述了双芯片方案的优势,并重点分享了高频电路设计中的电源、PCB布局布线等关键硬件设计技巧与避坑指南。同时,提供了通过SPI配置DDS芯片及利用Matlab生成任意波形的软件驱动方法,旨在帮助开发者打造一个覆盖10Hz至4200MHz的实用信号发生器。

weixin_36184718的博客 122

从‘和为给定数’到‘三数之和’:二分查找算法的通用解题框架与避坑指南

本文深入探讨了二分查找算法在解决有序数组问题中的应用,从基础的'和为给定数'问题扩展到复杂的'三数之和'场景。通过分析二分查找与双指针技术的结合使用,提供了高效的解题框架和避坑指南,特别适合信息学奥赛和算法竞赛的参赛者学习。文章还详细介绍了STL工具的应用和常见边界条件的处理方法。

weixin_38168322的博客 367

手把手教你在Keil/IAR中移植SEGGER_RTT组件(避坑指南+性能对比)

本文详细介绍了在Keil/IAR开发环境中移植SEGGER RTT调试组件的完整流程与优化技巧。通过对比传统串口调试,SEGGER RTT凭借零硬件占用、高速传输和双向交互等优势,显著提升嵌入式开发效率。文章包含配置步骤、性能调优方案及常见问题解决方案,是嵌入式开发者必备的实用指南。

y7z8a的博客 243

用python将dycom .dcm格式图像转换为nifti .nii

因为发现目前搜索到的多数中文教程并不能正确将FMRI图像正确转换,例如很多用simpleITk的seriesreader的,所以写了一下自己正确转换的方法。因为FMRI是一个4D数据,有时间轴,所以用seriesreader读写出来的图像把时间轴维度给降维了。当然你用SPM12工具的dycom import也是能正确转换的,但是我还是喜欢python这样的,代码直接简单。

qq_41103479的博客 3609

一篇文章带你学会二分(二分查找、二分答案)

众所周知,二分法是一个非常重要的算法,它可以在某些情况中代替遍历,使我们的时间 复杂度降低。二分法分为二分查找和二分答案,他们分别应用于不同的场景,其基本思想 是对于某个已知左端点和右端点的区间进行二分,以此达到最终效果。时间复杂度为O(log n)。

Wind_Breaker37的博客 2325

AT32F435/437开发实战:把SD卡变成U盘的完整指南(含源码解析)

本文提供了基于AT32F435/437微控制器将SD卡改造为U盘的完整实战指南。通过深入解析USB MSC协议与SDIO驱动的协同工作原理,详细介绍了硬件设计要点、软件架构融合、核心源码解析以及从编译到文件传输的完整调试流程,帮助开发者实现可靠的大容量存储设备扩展。

weixin_29159127的博客 410

算法 二分查找【Leo_Jose】

首先介绍一下二分查找 给出一组有序的数 1 2 3 4 5 6 7 8 9 10和待查找的数m,如果m在序列里,请输出它所在的位置,否则输出-1 如果我要找元素8,就得从左往右逐个搜索,要搜八次,其实如果是10的话,复杂度就是O(n) 然而如果这样不会超时的话,就不会出现二分查找这种算法了。。。。。 二分查找,顾名思义,就是分成两份查找。我们随便取一个数5,如果m>5,则m&g...

qq_43192522的博客 193

华为OD新系统机试真题 2026.5.10 - 美观的灯笼

华为OD新系统机试真题【美观的灯笼】,提供C语言、Java、C++、Python、Go、JavaScript源码实现,并提供完整思路讲解,以及在线OJ模拟做题。华为OD机试真题【美观的灯笼】

qq_45776114的博客 643

uniapp [安卓苹果App端] - 详细实现自定义水印相机功能,调用手机摄像头打开相机并在周围悬挂自定义水印,使用相机拍照后添加水印文字或样式,uniapp APP端水印相机完整源码,兼容强大可靠

uni-app,安卓Android,苹果ios,安卓app端,苹果App端,uniapp苹果app,水印相机,uniapp水印相机,Uniapp安卓app实现水印相机,uniapp苹果ios水印相机,打开系统相机拍照添加水印,地点打卡相机,水印相机(水印照片,图片加水印),uniapp自定义水印相机,制作水印相机给图片添加水印并且保存图片至本地,uniapp拍照图片加水印,水印相机功能,手机调起摄像头拍照时自动插入文字、图片动态水印效果,支持水印显示拍摄者当前城市定位、自由调整水印大小和位置,手机拍照时

🏆 前端领域优质创作者 1万+

【 C++ 】bitset位图的模拟实现

FLASH的博客 2208

大数据分析案例-基于随机森林模型对北京房价进行预测

自1998年我国取消了福利分房的政策后,房地产市场迅速开展蓬勃起来。同时,随着社会经济的快速开展,居民的经济条件越来越好,住房条件也在不断地提升。而住房是人民根本生活的保障,也是-一个家庭最重要的资产,从一定的层面.上反映了一个家庭整体的生活水王,多方面的因素使得房地产行业在短时间开展成为我国的支柱产业之一;成为了切实关乎人民生活和利益的重要产业。然而,随着房地产行业的开展,问题也慢慢突显出来,房价一直居高不下成为了一个大问题。 作为国家的支柱产业,房地产的稳定发展关乎国计民生。近几年,房

m0_64336780的博客 8827

二分&lower_bound( )和upper_bound( )

二分&lower_bound( )和upper_bound( ) 目录 一. 二分 二. lower_bound( )和upper_bound( ) ========================================================== 一. 二分 模板一(整数大于等于给定数的第一个数) int solve(int l, int r) { while ...

operation_hao的博客 260

温度PID控制PLC程序

温度PID稳定控制程序,适用于欧姆龙PLC,对其他PLC也具有很大参考价值

廖雪峰Python教程[完整版]

廖雪峰的python教程整理的,已经排好版了,而且还是完整的,适合小白

不务正业-二分基础

二分作为查找利器很实用: 本篇主要讲述二分理论 二分解题 二分STL解题 二分模板 非递推版本 int search(int x) //二分查找 { int left=1,right=n; while(left<=right) //注意这里必须等于 { int mid=(left+right)/2; if(x>num[mid

Cutepingping的博客 273

IDEA的使用指南

IDEA基于java的使用手册,可以最快速的上手,在使用中不断的丰富自己的使用技巧.

set中lower_bound用法

lower_bound在set中用法: 二分查找一个有序数列,返回第一个大于等于x的数,如果没找到,返回末尾的迭代器位置 #include&lt;bits/stdc++.h&gt; using namespace std; const int maxn=1e5+100; typedef long long ll; int N; //lowwe_bound:返回第一个&gt;=x的迭代器...

zsnowwolfy的博客 3万+

NTscan扫描工具

ntscan是一个扫描器,可以扫描没有密码和弱密码的共享,先到配置文件中填写猜测的用户名和密码,扫描过程中右侧出现的是扫描日志。

YTU 3734 查找最接近的元素 二分

时间限制:| 内存限制:题目描述在一个非降序列中,查找与给定值最接近的元素。

2302_79545206的博客 521

<C++> 位图

位图是一种十分特殊的数据结构,其主要依靠0和1表征状态,结合哈希的映射思想,即保证了速度,又保证了空间位图速度极快O(1)节省空间 使用粒度最细的比特位位图只能映射整型对于浮点符、字符串等数据无法做到很好的映射位图快速查找某个数据是否在一个集合中排序 + 去重求两个集合的交集、并集等操作系统中磁盘块标记。

weixin_61522065的博客 719

【C++】位图及其应用

公司面试题经常会用到的知识点!快来学习吧

睿的博客 457

【学习笔记】解析STL(标准模板库)

温馨提示:STL部分容器(string等)的在不开O2优化的情况下速度会很慢,使用请慎重一、map map是STL中的一个容器 使用它可以进行便捷的hash 1.头文件 #include< map >; 2.map变量的设置: map<类型1,类型2>变量名。其中类型1、2可以是int、char等,也可以是结构体,类型1存数组下标、类型2为元素的类型。 3.map中的find()函数:

Loi_MeiCo の 博客 622

查找(洛谷)

(假设索引从1开始)根据上面的方法,左点修改为中心值1,其原值就是1,也就是说没有更新,这样就会陷入一个死循环。正确的方法是如果中点值小于目标值,就把左点更新为中点加1.而右边不需要因为这里是小数部分被舍弃,也就是实际值大于该值,而右边不会。正确的做法是当一个目标值小于或等于中点时,将右点赋值为中间位置(为什么不是将等于条件放在目标值大于等于中点时,因为上面说了如果目标值大于中点值的时候将左值赋值为中点加一,这样会导致越过目标值)结束的条件就是左点小于右点。个整数,表示询问这些数字的编号,从。

m0_56053705的博客 493
上一篇: C++ 之归并排序模板
下一篇: C++ allocator 类的使用
zsiming
博客等级 码龄7年 43粉丝 74原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值