二分查找笔记

算法学习笔记【1】——二分查找 阅读详情

二分查找

二分查找是一种针对有序线性表的高效查找算法,在查找序列有序时,我们使用顺序查找和使用线性查找在数据规模较大的时候会有比较大的效率差别,很多人觉得二分就是整个左右指针往中间怼,就能达成目的,但是二分的细节还是蛮多的。

常规二分

对于常规的二分查找,一般是在指定的有序队列(无序如果有二分的需求的话就先排个序)中查找目标值,这个是二分最简单,也是最多为人所知的用法。

下面我们来看一下二分查找的代码:

#include <iostream>
#include <vector>

int binarySearch(vector<int> nums, int target){
	int left = 0,right = nums.size();
	while(left < right){
		int mid = (left + right)/2;
		if(nums[mid] == target){
			return mid;
		}else if(nums[mid] < target){
			left = mid + 1;
		}else if(nums[mid] > target){
			right = mid;
		}
	}
	return -1;
}

在这段代码里,有一个可以优化的地方,如果left + right > INT_MAX,那么我们的结果将会溢出,所以,我们可以写成这个样子

int mid = left + (right - left)/2;

还可以进一步写成

int mid = left + (right - left) >> 1;

这样就能防止隐藏的溢出错误了。

除此之外,可以看到我们使用的right = nums.size(); while的判别条件也是left < right,这是因为right是实际不可取的下表范围,而while的停止条件是left >= right,要是while的判别条件是left <= right,而且要查找的数是最后一个数的话,程序是会产生下标越界错误的。(相当于说我们划分的范围在[left,right)之间,区间左闭右开)。

总结起来就是:
判别条件为:“left < right” -> right应该取nums.size();
判别条件为:“left <= right” -> right应该取nums.size() - 1;

再说说为什么我们在判断条件中选择使用

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

– 在nums[mid] == target时,说明我们找到了,直接返回该下标。
– 在nums[mid] < target时,说明target在mid的右边,所以我们可以把区间收缩到[mid + 1,right),mid已经用过了。注意左闭右开,这是由上面while的判别条件(也是由我们right的取值)决定的。
– 同理,在nums[mid] > target时,我们把区间收缩到[left,mid)。
– 在有序区间没找到的话,那就返回-1。

查找左侧边界的二分查找

先上代码:

int B_S_lower_bound(vector<int> nums, int target) {
	if(nums.size() == 0){
		return -1;
	}
    int left = 0,right = nums.size(); 
    
    while(left < right) {
        int mid = left + (right - left) >> 1;
        if(nums[mid] == target){
        	right = mid;
        }else if(nums[mid] < target){		//锁定左边界 
			left = mid + 1;  
        }else if (nums[mid] > target)
			right = mid;
	}
    return left;
}

我们来分析一下里面的判断条件
– 当nums[mid] == target时,我们可以确定,mid的右边一定不是target的左边界所在的地方,所以我们把区间收缩成[left,mid);
– 当nums[mid] < target时,target的左边界一定在mid左边,因为mid已经使用过了,所以我们把区间收缩到[mid + 1,right);
– 当nums[mid] > target时,和nums[mid] == target同理,把区间收缩成[left,mid);

最终我们返回的是left,其实返回left和right都可以,因为终止条件是left == right;

查找右侧边界的二分查找

先上代码:

int B_S_upper_bound(vector<int> nums, int target) {
	if(nums.size() == 0){
		return -1;
	}
    int left = 0,right = nums.size(); 

    while(left < right) {
        int mid = left + (right - left) >> 1;
        if(nums[mid] == target){
        	left = mid + 1;
        }else if(nums[mid] < target){
            left = mid + 1; 		//锁定右边界 
        }else if (nums[mid] > target){
            right = mid; 
        }
    }
    return nums[left - 1] == target ? left - 1:left;
}

我们来分析一下里面的判断条件
– 当nums[mid] == target时,我们可以确定,mid的左边一定不是target的右边界所在的地方,所以我们把区间收缩成[mid + 1,right);
– 当nums[mid] < target时,同上,我们把区间收缩到[mid + 1,right);
– 当nums[mid] > target时,我们可以知道,target的右边界一定不会在右边,所以我们把区间收缩成[left,mid);

最终我们返回的是一个三元算式,本来是看着写的 return left - 1;
left或right无所谓,-1主要是因为我们收缩右边界时都会把mid抛弃,但实际可能mid就是target的右边界。

我自己进行修改主要是因为当我自己测试

   return left - 1;
}

vector<int> array = {1,3,4,5,5,7,9,10};
cout << B_S_lower_bound(array,5);
cout << B_S_upper_bound(array,6);

的时候,它输出的是3 4
个人认为5作为6的右边界是反直觉的.所以改成这样。(如果这样是错的劳请各位批评指正)

参考的大佬的文章:
我作了首诗,保你闭着眼睛也能写对二分查找
大佬的公众号:labuladong

【网络图】:附Origin详细画图教程 网络图,是一种由节点(或顶点)和连接这些节点的边(或链路)组成的图形结构。在网络图中,节点通常代表系统中的一个实体(如项目中的一项任务、通信网络中的一个设备、或运输网络中的一个站点),而边则代表这些实体之间的直接联系或流动(如任务的先后顺序、数据的传输路径、或乘客的旅行路线)。 有向图:如果边具有方向性,即从一个节点指向另一个节点,则称为有向图。这种图常用于表示具有明确先后顺序或方向性的系统,如项目管理中的任务依赖关系。 无向图:如果图中的边没有方向,则称为无向图。它适用于表示实体间相互关联但无明确方向性的 阅读详情

相关推荐

UE4项目迁移指南:如何无缝导入外部.uasset文件并保持材质关联

本文详细解析了将外部.uasset文件无缝导入UE4项目的专业方法。针对手动复制文件时常见的材质关联丢失问题,提供了使用引用查看器进行诊断和修复的实用技巧,并推荐使用引擎内置的“迁移”功能确保资源依赖关系的完整性,帮助开发者高效整合项目资源。

t8u9v0的博客 1046

二分查找基础学习

658. 找到 K 个最接近的元素 有序数组,找某个值,很明显的二分,先用二分找到数组中最接近x的那个元素,然后再左右扩张至长度k返回这k长度内所有的值就行。 class Solution { public: vector<int> findClosestElements(vector<int>& arr, int k, int x) { vector<int>ans; int p=0,q=arr.size()-1

weixin_62888410的博客 448

activemq_CVE-2015-5254_漏洞复现_源码分析

ActiveMQ-CVE-2015-5254

qq_51550750的博客 939

【二分查找】左侧边界、右侧边界、查找值

一直以来,搞不清楚关于二分查找的边界问题,不是这里越界,就是那里越界,调试很久也可能A不了,今天,来总结一下关于二分查找 1. 查找值 对于查找特定值来说,算是二分法的模板题目吧。 public int select(int[] nums, int target){ 2. 左侧边界 3. 右侧边界 ...

爱敲代码的小黄 3829

Applied Energy期刊小白论文投稿模板-流程经验分享

Applied Energy期刊小白论文投稿模板-流程经验分享,Elsevier期刊(爱思唯尔)投稿流程

zzu_Flyer的博客 4万+

从STM32转战华大HC32F4A0:我的踩坑实录与10个USART的灵活配置心得

本文分享了从STM32迁移至华大HC32F4A0的实战经验,重点解析了10个USART的灵活配置技巧及常见问题解决方案。通过对比STM32F407,详细介绍了HC32F4A0在外设灵活性、IO功能组设计及多串口应用中的优势,帮助开发者快速掌握国产芯片的开发要点。

weixin_30514745的博客 523

二分法-python-左右边界问题的阐述

二分法-python

2301_76874968的博客 477

数字人(对嘴型 Lip-sync)数据集 LRS2 介绍(含网盘链接)

LRS2(Lip Reading Sentences 2)是牛津大学与BBC合作开发的一个大规模唇语识别数据集,专门用于训练和评估数字人唇语同步(Lip-sync)技术。该数据集包含数千条来自BBC电视节目的口语句子,每个句子长度最多100个字符。官方网站为:https://www.robots.ox.ac.uk/~vgg/data/lip_reading/lrs2.html可惜需要认证,不过我已经下载好并存到网盘里了,有需要可适用如下链接下载。(仅供学习,请勿传播)

iioSnail的博客 1685

二分查找之搜索左侧边界和搜索右侧边界

二分查找之搜索左侧边界和搜索右侧边界

qq_41328481的博客 622

infercnv的实操

摘要: 博主在infercnv分析中遇到执行困难,外包服务不可靠(未按要求使用HMM方法)。通过优化策略(逐样本处理、精简细胞至1000个、固定随机种子)解决了运行问题,但HMM功能仍无法实现。最终参考Cell期刊标准设置阈值完成分析,后续将继续更新进展。该案例凸显了生物信息分析中自主优化的重要性。(150字)

xiaoyusang的博客 308

【unity游戏开发入门到精通——通用篇】Post Processing 后处理插件Post-process Volume 和 Volume最全基础使用说明

之前我已经实现了不少后处理功能,本文其实就是将他们归类整理,以便更好的查找和理解。在Unity中,后处理(Post-Processing)是在相机所捕捉的图像上应用一些特殊效果的过程,后处理会让图像视觉效果更好(前提是做的好)。这些效果的范围有非常细微的颜色调整,也包括整体的美术风格的大修,可以让场景看起来更加真实或风格化,或者只是变得更好看。就像我们都会用手机拍照,但很多时候我们拍的原始的相片都打不到我们想要的效果。比如照片可能亮度不够,颜色不饱和或者对比度不好等。

向宇的博客,专注php/web全栈 unity游戏开发,欢迎大家评论纠错 7896

东方 - 二分查找和二分答案

正常版本STL模板库版本。

m0_46192147的博客 615

23、电生理与CSD分析:探索大脑活动的前沿技术

本文介绍了电生理与电流源密度(CSD)分析在探索大脑活动中的前沿应用。从电生理技术的发展现状,到局部场电位(LFPs)的起源与解释,重点阐述了CSD分析的原理、实验方法及其在绘制皮层兴奋流、解析突触输入和研究自发振荡中的广泛应用。文章还总结了该领域的优势与挑战,并展望了技术改进、多模态融合、数据分析创新及临床拓展的未来方向,展示了这些技术在揭示大脑功能机制中的关键作用。

Apple的专栏 119

笔记【二分查找】

致谢 Just now, 幸得各位大佬(违规用户名1A8F1D09、血色黄昏、Callous_Murder)相助,才将我快飞掉的二分查找拽回来,万分感谢。 同时,也给我极大的教训( 不能只看老师的课件?!). 笔记 #include <cstdio> using namespace std; int a[1000005]; int n,m,l,r,mid,ans,num; int search(int x) { l=1,r=n ; while(l<=r) {

Rnin_Benny的博客 458

Probability and Statistics - 4th edition

Probability and Statistics - 4th edition

TMS_WebGMaps_1.9.8.0_Full_Source

TMS_WebGMaps_1.9.8.0_Full_Source 全源码 delphi cbuilder

二分查找学习笔记

二分查找

2302_80636518的博客 280

IDEA的使用指南

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

刷题笔记——二分查找/排序

描述给定一个长度为n的数组nums,请你找到峰值并返回其索引。数组可能包含多个峰值,在这种情况下,返回任何一个所在位置即可。1.峰值元素是指其值严格大于左右相邻值的元素。严格大于即不能有等于2.假设 nums[-1] = nums[n] = −∞。3.对于所有有效的 i 都有 nums[i]!4.你可以使用O(logN)的时间复杂度实现此问题吗?数据范围:如输入[2,4,1,2,7,8,4]时,会形成两个山峰,一个是索引为1,峰值为4的山峰,另一个是索引为5,峰值为8的山峰,如下图所示。

m0_74301144的博客 1057

华为的C语言编程规范.pdf

华为技术有限公司内部技术规范。本规范制定了编写C语言程序的基本原则、规则和建议。从代码的清晰、简洁、可测试、安全、程序效率、可移植各个方面对C语言编程作出了具体指导。

二分查找学习笔记(二):正整数和负整数的最大计数,咒语和药水的成功对数,H 指数 II

ps:笔记内容按本人理解整理,重思路

学习记录 826

LeetCode HOT100刷题笔记(十一):二分查找

ps:笔记和代码按本人理解整理,重思路

学习记录 856

算法笔记——【二分查找】

二分查找

qq_52671878的博客 932

菜鸡的刷题笔记1--二分查找

LeetCode刷题笔记

hunter_shadow的博客 393

二分查找学习笔记(三):寻找峰值,寻找峰值II

前两期有详细解释,后面题目是这个的变形(统一使用“前闭后闭”的写法方便理解)

学习记录 1710

《算法笔记》二分查找

目录二分查找(非递归实现)二分查找(递归实现)查找第一个大于目标值元素的下标大于目标值的第一个元素下标在一个有序数组中查找满足任意条件的第一个元素二分法的应用 二分查找(非递归实现) 二分查找的前提是有序,并且每次查找的范围都是闭区间 #include <iostream> #include<string.h> #include <algorithm> usi...

hjyp的博客 270

二分查找算法笔记

基本思路: y总二分模板: 二分模板一共有两个,分别适用于不同情况。 算法思路:假设目标值在闭区间[l, r]中, 每次将区间长度缩小一半,当l = r时,我们就找到了目标值。 版本1 当我们将区间[l, r]划分成[l, mid]和[mid + 1, r]时,其更新操作是r = mid或者l = mid + 1;,计算mid时不需要加1。 C++ 代码模板: int bsearch_1(int l, int r) { while (l < r) { ...

weixin_44798365的博客 207

算法笔记:二分查找

二分查找的概念、一般操作步骤、二分查找的模板、二分查找相关的算法题目以及详细的代码实现及思路和代码释义

凭心而动 1万+

二分查找——笔记详细版

二分查找——笔记详细版

Cap07博客 140

[笔记]二分查找——总结

二分查找,通过每次折半搜索范围来确定搜索对象。 时间复杂度:logN 准备: const int len1 = 10;//数组1的长度 const int len2 = 20;//数组2的长度 int array1[10] = {1,2,3,4,5,6,7,8,9,10}; int array2[20] = {1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5};...

qq_45179876的博客 186
上一篇: 临界区,互斥,竞争条件
下一篇: 蓝桥C++省赛B组--J:网络分析
binary str
博客等级 码龄8年 18粉丝 15原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值