当前位置: 首页 > news >正文

二分查找(精确查找、范围搜索)

目录

  • 1. 二分查找概述
  • 2. 精确查找
    • 2.1 【left,right】
    • 2. 2 【left,right)
  • 3. 范围查找
    • 总结

1. 二分查找概述

        二分查找法,也称为二分搜索法或折半查找法,是一种在有序数组中查找特定元素的搜索算法。其基本思想是,通过不断将待查找的区间分成两半,并与待查找的元素进行比较,根据比较结果调整查找区间,直到找到元素或区间被缩小至0为止。时间复杂度为O(log n)

  • 使用条件:二分查找要求数组必须是有序的,无论是升序还是降序。如果数组无序,则需要先进行排序操作。
  • 易错点:while循环过程中,left与right的关系容易错乱;left与right指针的移动容易错。
  • 查找情况:二分查找最常见的就是查找某一个序列中存在的精确值target,然而还有一部分是利用二分查找来进行范围划分。

2. 精确查找

        为了捋清楚终止条件与指针移动如何确定,需要先从搜索定义区间入手,搜索区间可以分为【left,right】和【left,right)。

2.1 【left,right】

当搜索区间为【left,right】时,说明二分查找过程中,每次搜索区间应该均需要满足该定义。此时二分查找步骤为:

  1. 确定查找区间:设数组为arr,查找范围为[left, right],初始时left=0,right=n-1,其中n为数组arr的长度。
  2. 确定循环条件:由于区间是左闭右闭,所以left = right符合定义区间,因此搜索过程中应当满足的条件为while(left <= right)
  3. 计算中间位置:mid = (left + right) / 2(注意,为了避免整数相加导致的整数溢出问题,有时也使用mid = left + (right - left) / 2的计算方式)。
  4. 比较中间元素与目标值: 如果arr[mid]等于目标值,则查找成功,返回mid。如果arr[mid]大于目标值,则说明目标值在左半部分,且arr[mid]将不会再需要处于搜索区间内了(因为arr[mid]已经一定不等于target了),则将查找范围更新为[left, mid-1],right = mid - 1。 如果arr[mid]小于目标值,则说明目标值在右半部分,且arr[mid]将不会再需要处于搜索区间内了(因为arr[mid]已经一定不等于target了),将查找范围更新为[mid+1, right],left = mid + 1
  5. 重复步骤2和步骤3:直到找到目标值或查找范围为空(即left > right),如果查找范围为空,则说明目标值不存在于数组中。
public static int binarySearch(int[] arr, int target) {  int left = 0;  int right = arr.length - 1;  while (left <= right) {  int mid = left + (right - left) / 2; // 防止溢出,同时更准确地找到中间位置  if (arr[mid] == target) {  return mid; // 找到目标元素,返回索引  } else if (arr[mid] < target) {  left = mid + 1; // 目标元素在右半部分  } else {  right = mid - 1; // 目标元素在左半部分  }  }  // 未找到目标元素,返回-1  return -1;  }  

2. 2 【left,right)

当搜索区间为【left,right)时:

  1. 确定查找区间:设数组为arr,查找范围为[left, right),初始时left=0,right=n,其中n为数组arr的长度。
  2. 确定循环条件:由于区间是左闭右开,所以left != right符合定义区间,因此搜索过程中应当满足的条件为while(left < right)
  3. 计算中间位置:mid = (left + right) / 2(注意,为了避免整数除法导致的精度问题,有时也使用mid = left + (right - left) / 2的计算方式)。
  4. 比较中间元素与目标值: 如果arr[mid]等于目标值,则查找成功,返回mid。如果arr[mid]大于目标值,则说明目标值在左半部分,arr[mid]将不会再需要处于搜索区间内了(因为arr[mid]已经一定不等于target了),并且right一直不在搜索范围内,所以将查找范围更新为[left, mid),right = mid。 如果arr[mid]小于目标值,则说明目标值在右半部分,且arr[mid]将不会再需要处于搜索区间内了(因为arr[mid]已经一定不等于target了),但是left必须在搜索区间内,所以将查找范围更新为[mid+1, right],left = mid + 1
  5. 重复步骤2和步骤3:直到找到目标值或查找范围为空(即left >= right),如果查找范围为空,则说明目标值不存在于数组中。
public static int binarySearch(int[] arr, int target) {  int left = 0;  int right = arr.length;  while (left < right) {  int mid = left + (right - left) / 2; // 防止溢出,同时更准确地找到中间位置  if (arr[mid] == target) {  return mid; // 找到目标元素,返回索引  } else if (arr[mid] < target) {  left = mid + 1; // 目标元素在右半部分  } else {  right = mid; // 目标元素在左半部分  }  }  // 未找到目标元素,返回-1  return -1;  }  

3. 范围查找

        有些时候,target不一定存在于序列中,但是我们想要得到大于target的序列区间,小于等于target的序列区间 或者 大于等于target的序列区间,小于target的序列区间。为了便于讨论,下面将循环条件定义为while(left <= right),指针移动方向为right = mid - 1,left = mid + 1

        由于定义区间为【left,right】,left <= right,搜索到最后left肯定会等于right,此时mid = left = right,下一次移动后将不满足循环条件退出。最后一次是left移动还是right移动?将直接影响最终查找的范围,即等于号归left区间还是right区间。假设代码如下:

while(left <= right){int mid = left + (right - left)/2;if(nums[mid] > target){//这里需要重点考虑,如果有等号存在,则说明如果mid所指就是target,则哪个指针继续跳一个单位,它就必不会等于mid,对应的区间中也就不会出现等于taget的情况//区间【left,n】所指向的值均 >target,区间【0,right】所指向的值均 <= targetright = mid + 1;}else{left = mid - 1;}
}
return left;

        可以自行验证,如果target不在序列中,最终left将指向第一个大于target的元素,right将指向最后一个小于target的元素。举例如下:

假设,序列{.....2,3,4,5.......}, target = 3.5,mid = left = right指向4,
此时target小于mid,之后执行right = mid - 1,right指向3,left仍指向4。
nums[【left,n】 ]  > target , nums[ 【0,right】 ] < target假设,序列{.....2,3,4,5.......}, target = 4.5,mid = left = right指向4,
此时target大于mid,之后执行left = mid + 1,left指向5,right仍指向4
依然是nums[【left,n】 ]  > target , nums[ 【0,right】 ] < target如果target存在于序列中,则最后执行right = mid - 1还是left = mid + 1将会影响target放入哪一个区间中。

        如果target存在于序列中,则mid最后所指就是target,所以最后一次移动指针之前,mid = left = right所指向的值就是target,此时哪个指针继续跳一个单位,它就必不会再有机会等于mid等于target,所以其对应的区间中也就不会出现等于taget的情况。
        因此上述 if 判断条件中的等号是否存在决定了是right指针会向左移动一格(此时,区间【left,n】所指向的值均 >=target,区间【0,right】所指向的值均 < target),还是left指针向右移动一格(此时,区间【left,n】所指向的值均 >target,区间【0,right】所指向的值均 <= target)

while(left <= right){int mid = left + (right - left)/2;if(nums[mid] >= target){//区间【left,n】所指向的值均 >=target,区间【0,right】所指向的值均 < targetright = mid + 1;}else{left = mid - 1;}
}
return left;

总结

left指向第一个符合if中判断条件的元素,right指向最后一个不符合if中判断条件的元素

  • 当判断条件为if(nums[mid] > target)时,最终nums[【left,n】 ] > target , nums[
    【0,right】 ] <= target
    ;
  • 当判断条件为if(nums[mid] >= target)时,最终nums[【left,n】 ] >= target , nums[
    【0,right】 ] < target
    ;

这种范围查找也非常适合在遇到元素重复出现,需要找到重复元素的第一个元素或者重复元素的最后一个的位置索引。

相关文章:

二分查找(精确查找、范围搜索)

目录 1. 二分查找概述2. 精确查找2.1 【left&#xff0c;right】2. 2 【left&#xff0c;right&#xff09; 3. 范围查找总结 1. 二分查找概述 二分查找法&#xff0c;也称为二分搜索法或折半查找法&#xff0c;是一种在有序数组中查找特定元素的搜索算法。其基本思想是&#x…...

软件工程简记

文章目录 一、软件工程要点之软件设计二、UML(Unified Modeling Language,统一建模语言)(一)UML 的整体分类与部分功能(二)UML 各类图的具体内容三、开发模型(一)多种开发模型的特点与问题四、设计模式(一)设计模式的总体概念与原则(二)软件结构设计原则(三)常见…...

【深度学习】【语音TTS】OpenVoice v2,测评,中英文语料,Docker镜像,对比GPT-SoVITS、FishAudio、BertVITS2

https://github.com/myshell-ai/OpenVoice/blob/main/docs/USAGE.md 实际体验OpenVoice v2的TTS效果。 文章目录 环境启动 jupyter代码代码分析主要模块和功能测试一些别的中文和中英文混合总结优点缺点对比GPT-SoVITS、FishAudio、BertVITS2使用我的Docker镜像快速体验OpenVo…...

Kotlin OpenCV 图像图像50 Haar 级联分类器模型

Kotlin OpenCV 图像图像50 Haar 级联分类器模型 1 OpenCV Haar 级联分类器模型2 Kotlin OpenCV Haar 测试代码 1 OpenCV Haar 级联分类器模型 Haar级联分类器是一种用于对象检测&#xff08;如人脸检测&#xff09;的机器学习算法。它由Paul Viola和Michael Jones在2001年提出…...

嗖嗖移动业务大厅(Java版)

首先对此项目说明一下&#xff0c;我只完成了项目的基本需求&#xff0c;另外增加了一个用户反馈的功能&#xff0c;但是可能项目中间使用嗖嗖这个功能还有一些需要完善的地方&#xff0c;或者还有一些小bug&#xff0c;就当给大家参考一下了&#xff0c;希望谅解。代码我也上传…...

hcia复习笔记

一、OSI 七层模型 应用层&#xff1a;为应用程序提供服务&#xff0c;如文件传输、电子邮件等。 表示层&#xff1a;数据格式转换、加密解密、压缩解压缩。 会话层&#xff1a;建立、维护和管理会话。 传输层&#xff1a;提供端到端的可靠或不可靠的数据传输服务&#xff0…...

pycharm中安装、使用扩展工具,以QT Designer为例

pycharm中安装、使用扩展工具&#xff0c;以QT Designer为例 第一步&#xff0c;下载QT Designer安装包。找到QT Designer.exe所在位置&#xff0c;复制路径 第二步&#xff0c;打开Pycharm&#xff0c;选择Setting&#xff0c;找到扩展工具&#xff08;External Tools&#xf…...

【Rust光年纪】Rust语言实用库汇总:从机器翻译到全文搜索引擎

优秀的Rust语言库探索&#xff1a;机器翻译、音频编解码和全文搜索引擎 前言 Rust语言在近年来迅速崛起&#xff0c;成为了一种备受欢迎的系统级编程语言。随着其生态系统的不断丰富&#xff0c;涌现出了许多优秀的库和工具。本文将重点介绍几个用于Rust语言的重要库&#xf…...

学习笔记 - 二极管的参数与选型

二极管 普通二极管&#xff1a; 1N4148(高频开关二极管) 整流二极管&#xff1a; 1N4007 1A 1000V1N5408 3A 1000V 肖特基二极管 &#xff08;白线边为阴极&#xff09; SS14 SS34 SS54 常见肖特基二极管参数 快恢复二极管 FR107 FR207 FR307 UF4007 可以用快恢复二…...

PMP--冲刺--易混概念

文章目录 十大知识领域一、整合管理项目管理计划与项目文件的区分&#xff1a; 二、范围管理三、进度管理赶工与快速跟进的区分&#xff1a;赶工增加资源&#xff0c;以最小的成本代价来压缩进度工期&#xff1b;快速跟进&#xff0c;将正常情况下按顺序进行的活动或阶段改为至…...

Resolving Maven dependencies

Maven是一种项目管理和构建工具&#xff0c;通常用于Java项目。这个过程包括下载项目所需的所有外部库和插件&#xff0c;并将它们添加到项目的构建路径中。具体来说&#xff0c;它正在处理名为“AAS_byBasyx”的项目或模块的依赖项。这种任务通常在你打开一个新的Maven项目或更…...

【Spring】SSM框架整合Spring和SpringMVC

目录 1.项目结构 2.项目的pom.xml文件 3.spring.xml和springMVC配置文件 4.database.properties和mybatis.xml配置文件 5. 代码编写 6.测试整合结果 1.项目结构 首先创建一个名为ssm_pro的Mavew项目&#xff0c;然后再在主目录和资源目录下&#xff0c;创建如下所示的结…...

优维2024年中思考:大模型赋予新一代运维的“非产品性”启示

近年来&#xff0c;人工智能在各个行业的应用大幅增加&#xff0c;人工智能技术取得重大进步的领域之一是IT运维。 去年四季度&#xff0c;优维科技敏锐地提出“新一代运维核心系统提供商”的战略新定位&#xff0c;决定将“DevOps及运维”回归到“运维”本身&#xff0c;但我…...

【中药网络药理学】筛选细胞衰老和预后相关基因(附分类代码和画图代码)

1、衰老相关基因 从HAGR和msigdb数据获取细胞衰老相关基因&#xff0c;将两者取交集后构建基因蛋白互作网络 HAGR数据库 该库本身提供了下载链接&#xff0c;我在下载后对其进行了清洗 msigdb数据库 以"aging"作为关键词&#xff0c;Search Filters中collection…...

华为的流程体系

缘由 2010年&#xff0c;华为销售额为1850亿元&#xff0c;其中国际市场占65%&#xff0c;净利润238亿元。当时&#xff0c;公司员工达11万人&#xff0c;公司处理合同达5万多个&#xff0c;290万个订单&#xff0c;大量的工作是手工处理&#xff0c;没有统一的流程支持&#…...

算法——长度最小的子数组209 对比代码随想录题解中对于result取值为Integer.MAX_VALUE的思考

具体解题过程可看代码随想录&#xff0c;我主要是对于为什么result也就是子数组和初始化要为Integer.MAX_VALUE有一个疑惑&#xff0c;为什么不是其他值&#xff0c;经过思考后我发现: 情况一&#xff1a;如果result为负数的话是不符合数组长度取值的一个规范的。 情况二&…...

图像处理案例03

HOGSVM数字识别 1 . 步骤2 . 代码 1 . 步骤 读入数据&#xff0c;把数据划分为训练集和测试集用hog提取特征用SVM训练数据测试、评价模型保存模型加载模型&#xff0c;应用模型 2 . 代码 import os import cv2 import sklearn import numpy as np from skimage.feature impo…...

【Kubernetes】k8s集群中kubectl的陈述式资源管理

目录 一.k8s集群资源管理方式分类 1.陈述式资源管理方式 2.声明式资源管理方式 二.陈述式资源管理方法 三.kubectl命令 四.项目生命周期 1.创建 kubectl create命令 2.发布 kubectl expose命令 3.更新 kubectl set 4.回滚 kubectl rollout 5.删除 k…...

串---顺序串实现

顺序串详解 本文档将详细介绍顺序串的基本概念、实现原理及其在 C 语言中的具体应用。通过本指南&#xff0c;读者将了解如何使用顺序串进行各种字符串操作。 1. 什么是顺序串&#xff1f; 顺序串是一种用于存储字符串的数据结构&#xff0c;它使用一组连续的内存空间来保存…...

吴恩达机器学习WEEK2

COURSE1 WEEK2 多维特征 在线性回归中&#xff0c;往往特征不止一个&#xff0c;而是具有多维特征 例如&#xff0c;在预测房价的例子中&#xff0c;我们知道更多的信息&#xff1a; x 1 x_1 x1​&#xff1a;房屋的面积 x 2 x_2 x2​&#xff1a;卧室的数目 x 3 x_3 x3​&a…...

yield and generator in python

首先&#xff0c;假设大家都对于pytyhon的List comprehension的使用有了一定经验&#xff08;它可以用于list&#xff0c;set&#xff0c;和dict哦&#xff09; 不熟悉的参考介绍&#xff1a; Comprehending Python’s Comprehensions – dbader.org generator generator是哦…...

spring原理(自学第六天)

Aware 接口及 InitializingBean 接口 今天将会学到Aware 接口及 InitializingBean 接口 我们可以先了解他们的作用&#xff1a; 1. Aware 接口用于注入一些与容器相关信息, 例如 a. BeanNameAware 注入 bean 的名字 b. BeanFactoryAware 注入…...

案例分享—国外优秀ui设计作品赏析

国外UI设计创意迭出&#xff0c;融合多元文化元素&#xff0c;以极简风搭配动态交互&#xff0c;打造沉浸式体验&#xff0c;色彩运用大胆前卫&#xff0c;引领界面设计新风尚 同时注重用户体验的深度挖掘&#xff0c;通过个性化定制与智能算法结合&#xff0c;让界面不仅美观且…...

【C++】简约与清晰的编程艺术

C编程的艺术&#xff1a;简约与清晰的实践之道 一、基础之美&#xff1a;基本类型与数据结构的力量二、函数与库类的艺术三、简约与清晰的实践之道 在C这一既古老又充满活力的编程语言世界里&#xff0c;程序员们常常面临着一个重要的选择&#xff1a;是追求代码的极致抽象与封…...

java之WIFI信号模块

开发步骤分为以下几点&#xff1a; 1.在 AndroidManifest 中声明相关权限&#xff08;网络和文件读写权限&#xff09; 声明权限: <uses-permission android:name"android.permission.ACCESS_WIFI_STATE" /> <uses-permission android:name"android.…...

Mybatis面试

Mybatis 面试 1、Mybatis 的执行流程是什么&#xff1f; 1、读取MyBatis配置文件&#xff1a;mybatis-config.xml 加载运行环境 和 映射文件 2、构造会话工厂 SqlSessionFactory &#xff08;全局只有一个&#xff09; 3、会话工厂创建SqlSession对象&#xff08;项目与数据…...

Centos 8系统xfs文件系统类型进行扩容缩容 (LVM)

Centos 8系统xfs文件系统类型进行扩容缩容 &#xff08;LVM&#xff09;,xfs分区类型是不支持正常缩容&#xff0c;只能强制缩容 1.磁盘情况&#xff1a;2.缩容home分区1.备份home数据&#xff1a;2.查找使用 /home 的进程&#xff1a;3.终止这些进程&#xff1a;4.卸载 /home …...

C语言基础知识之函数指针和指针函数

函数指针和指针函数 函数指针和指针函数指向函数的指针返回指针值的函数指针函数和函数指针的区别 问题1_1代码1_1结果1_1 函数指针和指针函数 指向函数的指针 用函数指针变量调用函数 可以用指针变量指向整型变量、字符串、数组&#xff0c;也可以指向一个函数。一个…...

【Unity】web gl inputFied 中文输入,同时支持TextMeshInputFied,支持全屏

同时支持TextMeshInputFied&#xff0c;支持全屏。 使用github包【WebGLInput】&#xff1a;https://github.com/kou-yeung/WebGLInput 需要资源的在这里也可以下载 https://download.csdn.net/download/weixin_46472622/89600795 用于unity web gl 中文输入&#xff0c;只需…...

vue3+vite全局引入less变量和函数

需要在vite配置 plugins: [css: {preprocessorOptions: {less: {additionalData: import "./src/styles/variables.module.less"; import "./src/views/Visualization/component/ViewportCom/px2viewport.less";,javascriptEnabled: true}}}, ]多个文件按…...

wordpress 用户等级/网页模版

本文节选自《.Net 软件设计新思维&#xff1a;像搭积木一样搭建软件 》一书 前 言 一个真实的故事 1996 年 10 月&#xff0c;一套经历了 2 年多时间开发出来的商务管理软件终于问世了&#xff0c;它带给我们无限的喜悦。 2 年多辛苦努力&#xff0c; 800 多个不眠之…...

哈尔滨口碑好的网站建设/西安seo关键词排名优化

<!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><title>test</title><style type"text/less">/*less的混合使用情景一&#xff1a;直接使用在一个选择器中引用另一个选择器&#xff08…...

学平面设计哪个学校好/北京seo排名技术

NFS是一款文件共享协议&#xff0c;读写性能强大使用简单&#xff0c;在win7系统中也加入了对NFS协议的支持&#xff0c;让快速设置Linux和Windows之间的文件共享成为可能&#xff0c;那么win7系统下怎么挂载NFS共享目录呢&#xff0c;下面给大家带来具体的操作方法供大家参考。…...

网站建设考虑哪些因素/色盲色弱测试

为什么80%的码农都做不了架构师&#xff1f;>>> 摘要&#xff1a; 数据库拆分后&#xff0c;数据分布到不同的数据库实例&#xff0c;可达到降低数据量&#xff0c;增加实例数的扩容目的。然而前途是美好的&#xff0c;道路是曲折的。一旦涉及拆分&#xff0c;就逃…...

彩票网站开发制作平台软件/被国家禁止访问的网站怎么打开

2010年全国自考高级语言程序设计模拟试卷(一)一、单项选择题(本大题共20小题&#xff0c;每小题1分&#xff0c;共20分)在每小题列出的四个选项中只有一个选项是符合题目要求的&#xff0c;请将正确选项前的字母填在题后的括号内。1.在定义 int a&#xff3b;5&#xff3d;&…...

wap网站开发价格/免费seo教程资源

不知道错在哪里 /* 给定两个斐波那契表示数&#xff0c;要求用标准化表达方式表达 然后将这两个数加起来&#xff0c;和也用标准化方式表达 思路&#xff1a;显然要将这两个数先用十进制表示&#xff0c;和也用十进制表示 然后在转化成二进制即可 1 1 2 3 5 8 13 21 34 用贪心…...