当前位置: 首页 > 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…...

AtCoder 第409​场初级竞赛 A~E题解

A Conflict 【题目链接】 原题链接&#xff1a;A - Conflict 【考点】 枚举 【题目大意】 找到是否有两人都想要的物品。 【解析】 遍历两端字符串&#xff0c;只有在同时为 o 时输出 Yes 并结束程序&#xff0c;否则输出 No。 【难度】 GESP三级 【代码参考】 #i…...

【Go】3、Go语言进阶与依赖管理

前言 本系列文章参考自稀土掘金上的 【字节内部课】公开课&#xff0c;做自我学习总结整理。 Go语言并发编程 Go语言原生支持并发编程&#xff0c;它的核心机制是 Goroutine 协程、Channel 通道&#xff0c;并基于CSP&#xff08;Communicating Sequential Processes&#xff0…...

Unit 1 深度强化学习简介

Deep RL Course ——Unit 1 Introduction 从理论和实践层面深入学习深度强化学习。学会使用知名的深度强化学习库&#xff0c;例如 Stable Baselines3、RL Baselines3 Zoo、Sample Factory 和 CleanRL。在独特的环境中训练智能体&#xff0c;比如 SnowballFight、Huggy the Do…...

Java面试专项一-准备篇

一、企业简历筛选规则 一般企业的简历筛选流程&#xff1a;首先由HR先筛选一部分简历后&#xff0c;在将简历给到对应的项目负责人后再进行下一步的操作。 HR如何筛选简历 例如&#xff1a;Boss直聘&#xff08;招聘方平台&#xff09; 直接按照条件进行筛选 例如&#xff1a…...

ip子接口配置及删除

配置永久生效的子接口&#xff0c;2个IP 都可以登录你这一台服务器。重启不失效。 永久的 [应用] vi /etc/sysconfig/network-scripts/ifcfg-eth0修改文件内内容 TYPE"Ethernet" BOOTPROTO"none" NAME"eth0" DEVICE"eth0" ONBOOT&q…...

算法岗面试经验分享-大模型篇

文章目录 A 基础语言模型A.1 TransformerA.2 Bert B 大语言模型结构B.1 GPTB.2 LLamaB.3 ChatGLMB.4 Qwen C 大语言模型微调C.1 Fine-tuningC.2 Adapter-tuningC.3 Prefix-tuningC.4 P-tuningC.5 LoRA A 基础语言模型 A.1 Transformer &#xff08;1&#xff09;资源 论文&a…...

【Go语言基础【12】】指针:声明、取地址、解引用

文章目录 零、概述&#xff1a;指针 vs. 引用&#xff08;类比其他语言&#xff09;一、指针基础概念二、指针声明与初始化三、指针操作符1. &&#xff1a;取地址&#xff08;拿到内存地址&#xff09;2. *&#xff1a;解引用&#xff08;拿到值&#xff09; 四、空指针&am…...

LangChain知识库管理后端接口:数据库操作详解—— 构建本地知识库系统的基础《二》

这段 Python 代码是一个完整的 知识库数据库操作模块&#xff0c;用于对本地知识库系统中的知识库进行增删改查&#xff08;CRUD&#xff09;操作。它基于 SQLAlchemy ORM 框架 和一个自定义的装饰器 with_session 实现数据库会话管理。 &#x1f4d8; 一、整体功能概述 该模块…...

Proxmox Mail Gateway安装指南:从零开始配置高效邮件过滤系统

&#x1f49d;&#x1f49d;&#x1f49d;欢迎莅临我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐&#xff1a;「storms…...

Java求职者面试指南:Spring、Spring Boot、Spring MVC与MyBatis技术解析

Java求职者面试指南&#xff1a;Spring、Spring Boot、Spring MVC与MyBatis技术解析 一、第一轮基础概念问题 1. Spring框架的核心容器是什么&#xff1f;它的作用是什么&#xff1f; Spring框架的核心容器是IoC&#xff08;控制反转&#xff09;容器。它的主要作用是管理对…...