二分查找(Binary Search)

C++ STL中的Binary search(二分查找) 常用操作   1.头文件 #include <algorithm> 2.使用方法 1.binary_search:查找某个元素是否出现。 a.函数模板:binary_search(arr[],arr[]+size ,  indx) b.参数说明:     arr[]: 数组首地址     size:数组元素个数     indx:需要查找的值 c.函数功能:  在数组... 阅读详情

二分查找也叫作折半查找。二分查找有两个要求,一个是数列有序,另一个是数列使用顺序存储结构。他的思想很简单,但是在书写过程中如果边界条件无法正确的确定,很容易陷入到循环中无法跳出。

二段性

二段性是集合中的元素有存在分界线,给定条件可以将集合中元素分为两部分,一部分满足条件,一部分不满足条件。

  1. 分界线之前的第一个元素,也就是最后一个满足条件的值,我们称为ML(Meeting Condition Last)
  2. 分界线之后的第一个元素,也就是第一个不满足该条件的值,我们称为NB(Not Meeting Condition Begining)

区间问题

此节主要讲二分查找的细节处理,如果要看二分的查找过程不建议看这篇,文中所讲的二分伪代码为:

l = -1,r = N + 1
while l + 1 != r
    m = l + (r - l >> 1)
    if judge(m) // 根据题目修改judge
        l = m
    else
        r = m
return l/r // 最终返回时根据需求进行返回

对于一个给定的数组 0    1    2    3    ⋯    ( N − 4 )    ( N − 3 )    ( N − 2 )    ( N − 1 )    N 0\ \ 1\ \ 2\ \ 3\ \ \cdots\ \ (N-4)\ \ (N-3)\ \ (N-2)\ \ (N-1)\ \ N 0  1  2  3  ⋯  (N−4)  (N−3)  (N−2)  (N−1)  N进行二分查找时,需考虑以下步骤

  1. 确定左右边界:这里确定左右边界分别为 − 1 -1 −1和 N + 1 N+1 N+1。

面对查找小于 0 0 0的最后一个数时,如果令左边界的值为 0 0 0,那么左边界的初始条件已经不满足问题要求了,因此采用0作为一个通用的二分求解方法的左边界并不是一个合理的方案。

同理,面对查找大于 N N N的第一个数,也不可以令右边界的值为1。

  1. 获得中点:使用 m = l + ( r − l > > 1 ) m = l + (r - l >> 1) m=l+(r−l>>1)作为获得重点的公式。

采用其他的公式,比如 m = l + r > > 1 m=l+r>>1 m=l+r>>1,也是可以的,但是为了防止 l l l与 r r r相加导致的数值溢出使用上面的公式。

  1. 收缩区间:使用 l = m l=m l=m和 r = m r=m r=m作为收缩区间的公式。

为了避免写出死循环,必须保证每次进入 w h i l e while while之后,可行区间都在变小,且最终推出循环。在此先引出程序终止的条件为 l + 1 = r l+1=r l+1=r,当面对 l + 1 = r l+1=r l+1=r,此时以满足终止条件所以无论 l l l和 r r r取多少,都会退出循环;当面对 l + 2 = r l+2=r l+2=r,中点为 m = l + 1 m=l+1 m=l+1,此时循环体内的收缩公式会将 m m m赋值给 l l l或者 r r r,再此达到终止条件,退出循环;当面对 l + 3 = r l+3=r l+3=r,按照 l + 2 = r l+2=r l+2=r里的分析,其最终会进入到 l + 2 = r l+2=r l+2=r或者 l + 1 = r l+1=r l+1=r的条件。

  1. 确定终止条件:这里终止条件为 l + 1 = r l + 1 = r l+1=r,即循环条件为 l + 1   ! = r l + 1\ != r l+1 !=r。

因为的目标时遍历整个数组,因此终止条件要确保所有的元素都可以被包含在内。同上面的收缩区间的公式相配合可以构成一个二分查找。

  1. l l l和 r r r的指向问题

l l l和 r r r的指向哪个数值,最终还是取决于judge条件。对于我们要查找小于零第一个数,其judge条件为 m < 0 m<0 m<0, l = − 1 l=-1 l=−1, r = 0 r=0 r=0。

对于一个例子 1 , 2 , 3 , 5 , 5 , 5 , 8 , 9 1, 2, 3, 5, 5, 5, 8, 9 1,2,3,5,5,5,8,9:

  1. 找到**小于 t t t**的最后一个数:

    class Solution {
        public int binarySearch(int[] arr, int t) {
            int l = -1, r = arr.length;
            while (l + 1 != r) {
                int m = l + (r - l >> 1);
                if (arr[m] < t) l = m; // judge条件:如果小于t,则让l=m;否则r=m
                else r = m;
            }
            return l; // 返回l
        }
    }
    
    Solution solution = new Solution();
    System.out.println(solution.binarySearch(new int[]{1, 2, 3, 5, 5, 5, 8, 9}, 5)); // 返回2,对应的值为3
    
  2. 找到**小于等于 t t t**的最后一个数:

    class Solution {
        public int binarySearch(int[] arr, int t) {
            int l = -1, r = arr.length;
            while (l + 1 != r) {
                int m = l + (r - l >> 1);
                if (arr[m] <= t) l = m; // judge条件:如果小于等于t,则让l=m;否则r=m
                else r = m;
            }
            return l; // 返回l
        }
    }
    
    Solution solution = new Solution();
    System.out.println(solution.binarySearch(new int[]{1, 2, 3, 5, 5, 5, 8, 9}, 5)); // 返回5,对应的值为5
    
  3. 找到**大于 t t t**的第一个数:(判断条件等价于找到小于等于 t t t的最后一个数)

    class Solution {
        public int binarySearch(int[] arr, int t) {
            int l = -1, r = arr.length;
            while (l + 1 != r) {
                int m = l + (r - l >> 1);
                if (arr[m] <= t) l = m; // judge条件:如果小于等于t,则让l=m;否则r=m
                else r = m;
            }
            return r; // 返回r
        }
    }
    
    Solution solution = new Solution();
    System.out.println(solution.binarySearch(new int[]{1, 2, 3, 5, 5, 5, 8, 9}, 5)); // 返回6,对应的值为8
    
  4. 找到大于等于 t t t的第一个数:(判断条件等价于找到小于等于 t t t的最后一个数)

    class Solution {
        public int binarySearch(int[] arr, int t) {
            int l = -1, r = arr.length;
            while (l + 1 != r) {
                int m = l + (r - l >> 1);
                if (arr[m] < t) l = m; // judge条件:如果小于t,则让l=m;否则r=m
                else r = m;
            }
            return r; // 返回r
        }
    }
    
    Solution solution = new Solution();
    System.out.println(solution.binarySearch(new int[]{1, 2, 3, 5, 5, 5, 8, 9}, 5)); // 返回3,对应的值为5 
    

参考文献:

  1. 二分查找为什么总是写错?
  2. 二分法的边界问题详细分析
【二分查找的实现方法----Java的binarySearch()方法】 本文将介绍二分查找的实现方法。并对Java中的binarySearch()方法进行具体研究 阅读详情

相关推荐

折半查找算法(BinarySearch)

折半查找算法(BinarySearch)的文字描述、图示描述和代码描述。

深入挖掘,筑基为先;知其然,知其所以然。 6522

binarySearch方法详解——全网最细!!!!!

binarySearch方法详解——全网最细!!!!!

weixin_43590500的博客 6454

二分查找函数binary_search

函数模版: templatetypename T>int  binary_search (T arr[],  int size,  T target) ;参数说明:T: 模版参数arr :  数组首地址, size: 数组元素个数, T target : 需要查找的值返回值: 如果数组中找到target, 返回其下标否则返回 -1要求数组元素顺序非递减templatetypename T>

touzani的专栏 1万+

Java中的binarySearch方法

大家好,我是雄雄,今天我们来看看java中的binarySearch方法! 前言:我们都知道,如果我们想要在一个集合中查找某个元素所在的位置时,可以使用list类自带的indexOf方法,简单方便还快捷。不过,Collections类也给我提供了个查找集合中元素的方法——binarySearch,但是这个方法和indexOf方法无论从检索原理还是返回值上来说,都有很大的差距! IndexOf方法 我们先来看看indexOf是怎么检索集合内元素的,示例代码如下: public static void mai.

穆雄雄的博客 1万+

算法-二分查找

现在我们来看一下二分查找二分查找的原理每次排除掉一半答案,使可能的答案区间快速缩小。二分查找log2(n)log_2(n)log2​(n),因为每次询问会使可行区间的长度变为原来的一半。我们再来看一下二分查找的思路我们设定一个初始的L和R,保证答案在[L,R]中,当[L,R]中不止有一个数字的时候,取区间的中点M,询问这个中点和答案的关系,来判断答案是M,还是位于[L,M-1]中,还是位于[M+1,R]中。二分查找的伪代码如下intL=区间左端点;二分查找。...

uncle_ll的博客 4398

Linux ELF文件解析:从file到readelf的完整工具链指南

ELF(可执行与可链接格式)是Linux系统中二进制文件的标准格式,定义了程序加载、内存布局和元数据组织方式。其核心原理在于通过程序头表描述执行视图、节区头表描述链接视图,实现代码与数据的结构化存储。这一格式的技术价值在于为程序调试、安全审计和性能优化提供了底层支持,尤其在动态链接、符号解析和内存保护机制中发挥关键作用。在应用场景上,系统管理员依赖ELF分析工具解决库依赖问题,安全研究员通过检查安全属性评估漏洞风险,开发者则利用反汇编进行代码调试。本文聚焦于file、readelf、objdump等工具链的

weixin_42691065的博客 635

基于STL的二分查找——binary_search函数

概述 C++ STL提供了标准二分查找相关实现。如下图所示,来自http://www.cplusplus.com/reference/algorithm/。 对应的函数功能如下表 函数名 函数作用 binary_search 在指定的范围内,使用二分查找某个值 lower_bound 在指定的范围内,使用二分查找某个值的左下界 upper_bound ...

努力中的老周的专栏 2830

关于AD中如何绘制原理图及其封装

AD中如何绘制原理图及其封装 题记:这是一个比较基础的知识,之所以我打算写一篇这样的笔记,主要是因为在日常生活中,我极少绘制特殊模块或芯片原理图及其封装。久而久之就忘记咋画了,有时需要画封装的时候又想不起来,网上的资料虽然一堆堆的,但往往只是仅原理图的绘制,或者是仅封装的绘制。为此我写一篇这样的笔记,记录绘制原理图及其封装的一条龙服务,感觉这对我而言尤为重要。 本文分为三大板块,依次是原理图的绘制、封装的绘制、二者的联立 第一板块——原理图的绘制 原理图的建立 第二板块——封装的绘制 第三板块——二者的

weixin_51130221的博客 7万+

STL binary_search二分查找算法

前面讲到的搜索算法都是对序列进行顺序搜索,而且没有事先对元素进行排序的要求。二分查找一般比顺序搜索要快,但要求序列中的元素是有序的。这主要是因为二分查找的搜索机制,图 1 说明了这种机制。 图1 二分查找 图 1 展示了在一个升序序列中二分查找 22 的过程。因为元素是升序排列的,所以查找机制使用小于运算符来查找元素。搜索降序序列需要使用小于运算符来比较元素。二分查找总是选择从序列中部的元素...

JIWilliams 724

手把手教你搭建《黑色沙漠》单机版:从下载到联机的完整指南(含GM工具使用)

本文提供《黑色沙漠》单机版从下载安装到GM工具使用及局域网联机的完整教程。详细解析不同版本选择、系统配置要求、常见问题解决,并分享GM工具高级命令和局域网联机设置技巧,帮助玩家轻松搭建个性化游戏环境。

weixin_28738165的博客 467

宇瞳杯视讯镜头完成版(除公差/鬼像分析)

宇瞳杯视讯镜头完成版(除公差/鬼像分析)

weixin_72050316的博客 1049

突破性能瓶颈:gh_mirrors/bi/binary_search中无界二分查找的巧妙实现

在数据处理和算法优化领域,高效的查找技术是突破性能瓶颈的关键。**gh_mirrors/bi/binary_search**项目提供了一系列改进的二分查找算法,其中无界二分查找(Monobound Binary Search)凭借独特的边界处理策略,在大规模数据场景下展现出显著的性能优势。本文将深入解析这一算法的实现原理、性能表现及实际应用价值。 ## 传统二分查找的局限性 传统二分查找算法在

gitblog_00641的博客 720

使用PostgreSQL构建高可用数据库集群

在现代企业级应用中,数据库的高可用性已成为业务连续性的核心要求。PostgreSQL作为一款功能强大的开源关系型数据库,其高可用架构的设计直接影响着系统的稳定性和可靠性。

九天的专栏 1258

二分查找binary_search()、lower_bound()、upper_bound()的用法

1.binary_search:查找某个元素是否出现。(排好序,递增) a.函数模板:binary_search(arr[],arr[]+size , indx) b.参数说明: arr[]: 数组首地址 size:数组元素个数 indx:需要查找的值 c.函数功能: 在数组中以二分法检索的方式查找,若在数组(要求数组元素非递减)中查找到indx元素则真,若查找不...

Hello,小高同学 735

【并发编程五】c++进程通信——共享内存(shared memmory)

现代操作系统,对于内存管理,采⽤的是虚拟内存技术,也就是每个进程都有⾃⼰独⽴的虚拟内存空间,不同进程的虚拟内存映射到不同的物理内存中。所以,即使进程 A中 和 进程 B中 的虚拟地址是⼀样的,其实访问的是不同的物理内存地址,对于数据的增删查改互不影响。这样这个进程写⼊的东⻄,另外⼀个进程⻢上就能看到了,都不需要拷⻉来拷⻉去,传来传去,⼤⼤提⾼了进程间通信的速度。⽤了共享内存通信⽅式,带来新的问题,那就是如果多个进程同时修改同⼀个共享内存,很有可能就冲突了。那共享内存的⽅式,就很好的解决了这⼀问题。

junxuezheng的博客 1万+

复现CVE-2014-085(Apache ZooKeeper 未授权访问漏洞)

默认安装配置完的zookeeper允许未授权访问,管理员未配置访问控制列表(ACL)。导致攻击者可以在默认开放的2181端口下通过执行envi命令获得大量敏感信息(系统名称、java环境)导致任意用户可以在网络不受限的情况下进行未授权访问读取数据。

记录并分享学习安全的知识点.. 2175

STL算法 | 查找函数 find()、二分查找binary_search/upper_bound、子序列查找search

文章目录一、find系列函数(单个元素顺序查找)1. find 搜索等于 value 的元素。2. find_if 搜索谓词 p 对其返回 true 的元素3. find_if_not 搜索谓词 q 对其返回 false 的元素。测试用例一、二分查找系列函数(单个元素二分查找)1. lower_bound 二分查找大于等于2. upper_bound 二分查找大于3. equal_range 二分查找等价区间4. binary_search 二分查找是否存在元素value测试用例三、子序列查找 search

专注于C/C++/Linux领域创作 2392

使用Google Earth Engine下载JRC全球水体数据

通过Google Earth Engine平台和提供的源代码,研究人员和水资源管理者可以方便地获取和利用这一重要的水资源监测数据集,从而开展相关的研究和决策支持工作。要使用Google Earth Engine下载JRC全球水体数据,首先需要在Google Earth Engine平台上进行注册和登录。JRC全球水体数据是由欧洲联合研究中心开发的高分辨率全球水体分类数据集,覆盖了整个地球的陆地和水域。下载完成后,你可以使用各种遥感数据处理软件来打开和分析这些数据,以满足不同的研究和应用需求。

LrlDebug的博客 1158

STL中的二分查找——lower_bound 、upper_bound 、binary_search

二分查找很简单,原理就不说了。STL中关于二分查找的函数有三个lower_bound 、upper_bound 、binary_search 。这三个函数都运用于有序区间(当然这也是运用二分查找的前提)。        其中如果寻找的value存在,那么lower_bound返回一个迭代器指向其中第一个这个元素。upper_bound返回一个迭代器指向其中最后一个这个元素的下一个位置(明确点说就

SHUI 1290

文档:亲测可用解决vnc灰屏,黑屏,鼠标大黑叉情况

主要解决vnc-viewer灰屏,黑屏,鼠标大黑叉等现象,详细见文档。

VC中sqlite的使用

在VC中对sqlite的使用,实现数据库大批数据的快速插入,读取数据库中的数据在ListCtrl中显示

二分查找 Binary Search

二分查找法 Binary Search

底层码农 6521

计算机控制技术及应用

《计算机控制技术及应用》通过总结作者的科研成果和吸收国内外的先进理论、方法和技术,以计算机控制系统的网络化、开放化、智能化和集成化发展趋势为主线索,主要介绍计算机控制系统的基本概念和计算机控制系统的典型形式,计算机控制系统的数学描述与基本分析方法,以及数字PID控制器、最少拍控制系统、达林算法、状态变量设计法等设计方法及其各种改进算法。重点突出计算机控制系统输入输出通道接口的设计方法和典型控制系统的设计案例与实现方法等。

上一篇: 二叉搜索树(Binary Search Tree)
下一篇: 计数排序(Counting Sort)
小菜2小白
博客等级 码龄4年 4粉丝 25原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值