二分查找算法介绍(边界值、循环条件、值的变化、二分查找的原理、异常处理)

一、二分查找法原理介绍

        二分查找是经典的查找算法之一,其原理也非常简单。

        对于已排序的数组(假设是整型,如果非整型,如果有排序和大小比较的定义,也可以使用二分查找),我们每次判断中间值与目标值的大小,从而排除另外半边。

       如下图所示,我们每次可以排除现有数组的一半及以上数据,也就是说,二分查找,利用了排除的原理。

二、二分查找的3个关键数据

        left:确定左边界,比如上图原数据的0。

        right:确定右边界,比如上图原数据的8。(有些题解,会用9表示,则right仍是右边界,只是此边界无法取到)

        middle:从中间开始判断,每次排除左边或右边的所有数据。

三、left、right的取值条件

        在此先说明一个重点

        left、right是限定数组的,每一次排除元素,都要保证得到的新数组,没有重复、缺失。【缺失可能出错,重复会导致复杂情况】

        缺失的情况其实一般不会出现。

        我们疑虑的,主要是这个问题:

        当 middle > 目标值时, 排除右边区域,那么:

        right = middle,还是

        right = middle - 1呢?

        如果用 right = middle,因为有重复数据,会不会更加保险呢?

        别急,接着往下看。

四、二分查找边界值处理【关键是,仅1个元素的数组】

        抽象left、right的选值,因为这并非重点,如果明白边界值处理,就能理解left、right选值和while循环条件的原理。

        第一,空数组【】

        假设我们有一个空数组,必定无所需元素,所以直接返回null。

        第二,1元素数组【a】

        假设数组中,只有一个元素a,此时只要判断a==目标值否,就能知道数组中是否有值。

        第三,其它情况。

        我们已知left、right是限定数组的,那么,如果目前数组的中心值middle,刚好等于目标值,就能返回答案。【这是最简单的情况,而且不用考虑1、2情况】

        但是常常会出现的问题是:

        1.数组中没有目标值。

        2.很可能一直迭代到left==right,或者left+1=right时,才得到目标值。【而第2个情况,又得从while条件里,找正确与否。】

                不考虑 left+2 == right ,或者 left+3 == right 的原因

        left+2 == right:中间值middle,可以等于

        ( left + right ) / 2                      比如【1,4,6】

       无论排除左边,还是右边,最后都剩下1元素数组【1】或者【6】

        left+3 == right : 中间值middle,为

        left+1【(left+left+3)除以2,化简】  比如【1, 4, 6, 9】

        那么,左边排除后,剩下【6,9】,即新问题【 left+1 == right 】的解决。

        右边排除后,剩下【1】,即为单元素问题。

        我们忽略第1个问题,因为如果解决了第2个问题,第1个问题也是迎刃而解。

                考虑2种情况, left == right,和 left+1 == right

        正如“第二,1元素数组【a】”所说,只要判断中间值 middle == (left+right)/2 == left与目标值的关系,就能知道数组中有无目标值。

        我们统一一种算法【满足开头所说的重点】:

        1. middle大于目标值,则舍弃右边,所以   right = middle - 1;

        2. middle小于目标值,则舍弃左边,所以   left = middle + 1;

        3. middle = (left + right) /2;

        这种算法可行吗?

        显然,当 left 恰好为 right 时,middle正好等于 left,恰好可以判断。

        所以,在单元素中满足。

        对于 left +1 == right呢?

        假设我们刚进入这个数组,那么 middle = left 【 ( left+left+1 ) / 2 】

        那么,经过判断,要不就说明 middle > 目标值,数组中无目标值。

        要不就是, middle < 目标值,判断右边的最后1个元素。

        这一步结束后,结果即1元素数组【a】的解法(或者成功判断)

        所以,本题满足。

五、while的循环条件

        我们已经了解left、right的取值,最后的重点是,while条件该如何处理?

        其实一般都知道,left < right 时,一般都可以继续执行,可是 left == right 时,该怎么办呢?

        结合上面的思路,其实一下就能看出来,如果 left == right, 不就恰好是 1元素的数组吗?

        那用 left <= right 作为循环条件,会不会无限循环呢?

        不会,因为我们把middle也排除了,做到了无重复,所以这个问题不算复杂。

六、异常处理

        考虑异常。

        数组元素重复

        最经典的,就是每一次比较middle后,使:

        left = middle;

        right = middle;

        出现的两种情况:

        假设现在有 1元素数组【a】。

        middle、left、right都指向a,无论a比目标值大、小,只要不等于,那么left、right会永远指向a,陷入死循环。

        当然,也有的情况是 2元素数组【a,b】

        left指向a, right指向b,此时middle指向a。

        并且,a比目标值小。

        此时,left = middle。

        而middle又是 left+right的二分之一,恰好是left,又是死循环。

        解决:

        特地判断 left == right, 和 left+1 == right两种情况。【那么代码就不够简洁,反而复杂了。】

        循环条件异常:

        对于 left初值为0, right初值为len-1。

        如果条件是 left < right ,明显会缺失数据。【不再解释】

        如果right初值为len呢?

        这是常常出现的问题,此时我们可以发现,right指向空元素。

        为了保持数据结构的统一性,必须在接下来的更新里,使得right永远指向空元素【不一定是无值,但是要使 right 指向的区间,已经被排除过。】

        这时,在排除时,就可以:

        right = middle。

        那么循环条件也明显了,如果 left <= right,那么在最后,一定会出现面对 空集合 ,却一直判断的情况。【注:空集合是我们更新后,新数组为null, 而在原数组中,(left+right )/2指向的元素,仍然有值】

七、结语

        总之,一定要做好 数组 更新的一致性,做好了这个,就能解题了。

         我是蚊子码农,如有补充或者疑问,欢迎在评论区留言。个人的知识体系可能没有那么完善,希望各位多多指正,谢谢大家。

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

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

相关文章

Golang TCP网络编程

文章目录 网络编程介绍TCP网络编程服务器监听客户端连接服务器服务端获取连接向连接中写入数据从连接中读取数据关闭连接/监听器 简易的TCP回声服务器效果展示服务端处理逻辑客户端处理逻辑 网络编程介绍 网络编程介绍 网络编程是指通过计算机网络实现程序间通信的一种编程技术…

三十五、openlayers官网示例Dynamic Data——在地图上加载动态数据形成动画效果

官网demo地址&#xff1a; Dynamic Data 初始化地图 const tileLayer new TileLayer({source: new OSM(),});const map new Map({layers: [tileLayer],target: "map",view: new View({center: [0, 0],zoom: 2,}),}); 创建了三个样式 const imageStyle new Style(…

黑马微服务实用篇知识梳理

1、微服务治理 1.1服务注册与发现Eureka和Nacos a、nacos和eureka&#xff0c;二者都支持服务注册与发现&#xff0c;但nacos还包括了动态配置管理、服务健康监测、动态路由等功能&#xff0c;是更全面的服务管理平台 b、eureka需要独立部署为服务并运行&#xff0c;需要自行搭…

师彼长技以助己(3)逻辑思维

师彼长技以助己&#xff08;3&#xff09;逻辑思维 前言 上一篇文章进行了工程思维和产品思维的测试&#xff0c;并介绍了几个比较重要的产品思维模型。接下来本篇介绍工程思维。&#xff08;注意产品思维并不代表产品经理思维&#xff0c;工程思维也并不代表工程师思维&…

【用户画像】用户偏好购物模型BP

一、前言 用户购物偏好模型BP&#xff08;Buyer Preferences Model&#xff09;旨在通过对用户购物行为的深入分析和建模&#xff0c;以量化用户对不同商品或服务的偏好程度。该模型对于电商平台、零售商以及其他涉及消费者决策的商业实体来说&#xff0c;具有重要的应用价值。…

linux,lseek,append用法

打开写的.c文件 内容为 代码 <sys/stat.h> #include <fcntl.h> #include<stdio.h> #include<unistd.h> #include<string.h>//off_t lseek(int fd, off_t offset, int whence); //int open(const char *pathname, int flags); //int open(const …

二类电商想做爆品还是得会选品

对于二类电商&#xff0c;尤其是电商新手而言&#xff0c;往往很多人都不知道自己该如何选品&#xff0c;在哪里选品&#xff0c;以及如何谈品等等的难题。想要挑选具有潜力的商品&#xff0c;首先我们需要梳理好商品选择的逻辑&#xff1a; 二类电商的特点&#xff1f;你要投…

装机必备——360驱动大师安装教程

装机必备——360驱动大师安装教程 软件下载 软件名称&#xff1a;360驱动大师2.0beta 软件语言&#xff1a;简体中文 软件大小&#xff1a;13.87M系统要求&#xff1a;Windows7或更高&#xff0c; 32/64位操作系统 硬件要求&#xff1a;CPU2GHz &#xff0c;RAM2G或更高 下载…

36【Aseprite 作图】蒸笼盖——拆解

1 蒸笼盖框架 里圈和外圈的形状都是一样的 扶手处&#xff0c;2 1 2 2 2&#xff08;最好都是2&#xff0c;拐角处用1&#xff09; 2 上色 中间的波浪&#xff0c;是2 2 2 上&#xff08;再 2 2 2 下&#xff09; 下方阴影&#xff0c;左边的阴影&#xff0c;右边的阴影颜色…

冯喜运:6.3黄金原油晚间最新行情及独家操作策略指导

【黄金消息面分析】&#xff1a;在全球经济的波动和不确定性中&#xff0c;黄金作为传统的避险资产&#xff0c;其价格走势和市场分析一直是投资者关注的焦点。本周一&#xff08;北京时间6月3日&#xff09;&#xff0c;现货黄金价格基本持平&#xff0c;交易商正在等待本周公…

一个AI板卡电脑--香橙派 AIpro

本文算是一个开箱测评&#xff0c;主要评估它和一个电脑的距离。 香橙派官网&#xff1a;香橙派(Orange Pi)-Orange Pi官网-香橙派开发板,开源硬件,开源软件,开源芯片,电脑键盘香橙派&#xff08;Orange Pi&#xff09;是深圳市迅龙软件有限公司旗下开源产品品牌;香橙派&#x…

抖音小店怎么找厂家代发?从沟通到发货,全流程不容错过!

哈喽~ 我是电商月月 新手做抖音小店&#xff0c;无货源模式的商家不知道怎么找货源&#xff1f; 今天月月就给大家讲解一下抖音小店从找厂家&#xff0c;到和厂家沟通&#xff0c;最后协商发货的方法步骤都有哪些&#xff1f; 满满干货&#xff0c;不容错过&#xff0c;建议…

游戏找不到d3dcompiler43.dll怎么办,分享5种有效的解决方法

在计算机使用过程中&#xff0c;我们经常会遇到一些错误提示&#xff0c;其中之一就是找不到某个文件。其中&#xff0c;找不到d3dcompiler43.dll是一个常见的问题。这个问题通常出现在运行某些游戏或应用程序时&#xff0c;由于缺少了d3dcompiler43.dll文件&#xff0c;导致程…

openeuler欧拉系统连不上网,ping百度报错,ping: www.baidu.com: Name or service not known

一、现象 使用华为 openeuler 系统连不上网&#xff0c;ping 百度报如下错误 ↓ ping: www.baidu.com: Name or service not known二、原因 没有配置dns服务器 三、解决办法 进入网络配置文件存放文件夹 cd /etc/sysconfig/network-scripts/查看对应的网口文件 ls ps: 不同系…

C语言:(动态内存管理)

目录 动态内存有什么用呢 malloc函数 开辟失败示范 free函数 calloc函数 realloc函数 当然realooc也可以开辟空间 常⻅的动态内存的错误 对NULL指针的解引⽤操作 对动态内存开辟的空间越界访问 对⾮动态开辟内存使⽤free释放 使⽤free释放⼀块动态开辟内存的⼀部分 …

TCP三次握手四次挥手,滑动窗口

TCP三次握手 TCP&#xff08;传输控制协议&#xff09;是一种重要的网络协议&#xff0c;它属于互联网协议套件中的传输层&#xff0c;主要用于在不可靠的互联网上提供可靠的、有序的和无差错的数据传输。下面详细介绍TCP的工作原理&#xff0c;包括其连接建立的三次握手过程。…

类和对象(下)【初始化列表】【static成员】【友元】等..... .及【练习题】

类和对象&#xff08;下&#xff09; 1.再谈构造函数 1.1构造函数体赋值 在创建对象时&#xff0c;编译器通过调用构造函数&#xff0c;给对象中各个成员变量一个合适的初始值。 // 初始化列表 # include<iostream> using namespace std;class Date { public:// 构造…

机器学习第十一次课

前言 从现在开始进入神经网络的领域了 正文 先是一段历史介绍,这个就跳过吧,我觉得这里最重要的就是反向传播这里 反向传播 反向传播&#xff08;Backpropagation&#xff09;是一种训练人工神经网络的算法&#xff0c;它通过计算损失函数关于网络参数的梯度来调整网络参数…

java基础篇(1)

JDK是什么?有哪些内容组成?JDK是Java开发工具包 JVM虚拟机: Java程序运行的地方 核心类库: Java已经写好的东西&#xff0c;我们可以直接用开发工具: javac、java、jdb、jhat.. JRE是什么?有哪些内容组成? JRE是Java运行环境 JVM、核心类库、运行工具 JDK&#xff0c;JRE&…

Vulnhub项目:HACKSUDO: THOR

1、靶机地址 hacksudo: Thor ~ VulnHubhacksudo: Thor, made by Vishal Waghmare. Download & walkthrough links are available.https://vulnhub.com/entry/hacksudo-thor,733/ 2、渗透过程 来了来了&#xff0c;开搞&#xff0c;先看目标 56.161&#xff0c;本机 56.1…