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

二分查找法详解(6种变形)

前言
在之前的博客中,我给大家介绍了最基础的二分查找法(没学的话点我点我!)

今天我将带大家学习二分法的六种变形如何使用,小伙伴们,快来开始今天的学习吧!
在这里插入图片描述

文章目录

  • 1,查找第一个(从左到右)= 目标值的,若不存在返回 -1
  • 2,查找第一个 >= 目标值的
  • 3,查找第一个 > 目标值的
  • 4,查找最后一个 = 目标值的 ,若不存在返回- 1
  • 5,查找最后一个 <= 目标值的
  • 6,查找最后一个 < 目标值的
  • 总结

1,查找第一个(从左到右)= 目标值的,若不存在返回 -1

与原版二分法其实差不多,当一个数组中有重复的目标值时,使用该方法可以找到从左到右第一个等于目标值的下标。
因为我们要找的是第一个等于目标值的下标,那我们不仅仅在arr[mid] > key时去左边找,在arr[mid]>= key我们也要去找,因为我们需要要最左边等于目标值的下标。
注意事项
最后我们要判断left是否越界(left 有可能等于数组元素的个数),而且最后arr[left]是否等于要找的key。
代码:

int efcz(int* arr, int key,int left,int right)
{int len = right+1;//数组长度(元素个数)int mid = (left + right) / 2;while (left <= right){mid = (left + right) / 2;if (arr[mid] >= key){right = mid - 1;}if (arr[mid] < key){left = mid + 1;}}if (left < len&&arr[left] != key)//判断一下是否找到元素return -1;elsereturn left;
}
int main()
{int arr[10] = { 1,2,3,5,5,5,5,5,5,6 };//创建数组int key = 5;//目标值为5int left = 0;//设置左右起点int right = sizeof(arr) / sizeof(arr[0]);printf("%d", efcz(arr, key,left,right));//进入二分查找函数return 0;
}

2,查找第一个 >= 目标值的

这次我们需要查找第一个大于等于目标值的下标,这次我们不需要判断left越界,如果越界就说明没有找到,说明整个数组都比目标值要小。
代码:

//思路和第一种一样,我就不加注释了,如果不懂可以私信问我
int efcz(int* arr, int key, int left, int right)
{int mid = (left + right) / 2;while (left <= right){mid = (left + right) / 2;if (arr[mid] >= key){right = mid - 1;}if (arr[mid] < key){left = mid + 1;}}return left;
}
int main()
{int arr[10] = { 1,2,3,5,5,5,5,5,6,8 };int key = 7;int left = 0;int right = sizeof(arr) / sizeof(arr[0]);printf("%d", efcz(arr, key, left, right));return 0;
}

3,查找第一个 > 目标值的

这次我们需要查找第一个大于目标值的下标,这次我们同样不需要判断left越界,如果越界就说明没有找到,说明整个数组都比目标值要小。
另外我们需要改变一下函数内部的判断条件,当arr[mid] <= key时,left = mid + 1
因为我们不是要找相等的,是要找大于目标值的。
代码:

//思路和第一种一样,我就不加注释了,如果不懂可以私信问我
int efcz(int* arr, int key, int left, int right)
{int mid = (left + right) / 2;while (left <= right){mid = (left + right) / 2;if (arr[mid] > key){right = mid - 1;}if (arr[mid] <= key){left = mid + 1;}}return left;
}
int main()
{int arr[10] = { 1,2,3,5,5,5,5,5,6,8 };int key = 5;int left = 0;int right = sizeof(arr) / sizeof(arr[0]);printf("%d", efcz(arr, key, left, right));return 0;
}

4,查找最后一个 = 目标值的 ,若不存在返回- 1

因为我们要找的是第一个等于目标值的下标,那我们不仅仅在arr[mid] < key时去右边找,在arr[mid]>= key我们也要去找,因为我们需要要最右边边等于目标值的下标。
注意事项
最后我们要判断right是否越界(right 有可能等于-1),而且最后arr[right]是否等于要找的key。
代码:

//思路和第一种一样,我就不加注释了,如果不懂可以私信问我
int efcz(int* arr, int key, int left, int right)
{int mid = (left + right) / 2;while (left <= right){mid = (left + right) / 2;if (arr[mid] > key){right = mid - 1;}if (arr[mid] <= key){left = mid + 1;}}if (right >= 0 && arr[right] == key)//判断是否找到return right;elsereturn -1;
}
int main()
{int arr[10] = { 1,2,3,5,5,5,5,5,6,8 };int key = 5;int left = 0;int right = sizeof(arr) / sizeof(arr[0]);printf("%d", efcz(arr, key, left, right));return 0;
}

5,查找最后一个 <= 目标值的

这次我们需要查找第一个小于等于目标值的下标,这次我们不需要判断right越界,如果越界就说明没有找到,说明整个数组都比目标值要大。
代码:

//思路和第一种一样,我就不加注释了,如果不懂可以私信问我
int efcz(int* arr, int key, int left, int right)
{int mid = (left + right) / 2;while (left <= right){mid = (left + right) / 2;if (arr[mid] > key){right = mid - 1;}if (arr[mid] <= key){left = mid + 1;}}return right;
}
int main()
{int arr[10] = { 1,2,3,5,5,5,5,5,6,8 };int key = 4;int left = 0;int right = sizeof(arr) / sizeof(arr[0]);printf("%d", efcz(arr, key, left, right));return 0;
}

6,查找最后一个 < 目标值的

这次我们需要查找第一个小于目标值的下标,这次我们同样不需要判断right越界,如果越界就说明没有找到,说明整个数组都比目标值要大。
另外我们也需要改变一下函数内部的判断条件,当arr[mid] >= key时,right = mid - 1,因为我们不是要找相等的,是要找小于目标值的。
代码:

//思路和第一种一样,我就不加注释了,如果不懂可以私信问我
int efcz(int* arr, int key, int left, int right)
{int mid = (left + right) / 2;while (left <= right){mid = (left + right) / 2;if (arr[mid] >= key){right = mid - 1;}if (arr[mid] < key){left = mid + 1;}}return right;
}
int main()
{int arr[10] = { 1,2,3,5,5,5,5,5,6,8 };int key = 5;int left = 0;int right = sizeof(arr) / sizeof(arr[0]);printf("%d", efcz(arr, key, left, right));return 0;
}

总结

我认为可以分两组记忆这六种变形,前三组一类,后三组一类,前三组都是返回left,后三组都是返回right,同时我们会发现,第一种和第四种,第二种和第五种,第三种和第六种都十分的相似,所以自己练练就能掌握,而且不容易忘记,本期的分享就到这里,如果觉得博主讲的不错的话,千万不要忘记给博主一个关注,点赞,收藏哦~,小伙伴们,我们下期再见!

相关文章:

二分查找法详解(6种变形)

前言 在之前的博客中&#xff0c;我给大家介绍了最基础的二分查找法&#xff08;没学的话点我点我&#xff01;&#xff09; 今天我将带大家学习二分法的六种变形如何使用&#xff0c;小伙伴们&#xff0c;快来开始今天的学习吧&#xff01; 文章目录 1&#xff0c;查找第一个…...

uniapp uview 页面多个select组件回显处理,默认选中

<view class"add-item column space-around" click"selectClick(1)"><text class"w-s-color-3 f-28">商品分类</text><view class"w-100 space-between"><!-- 第一个参数为你的单选数组&#xff0c;第二个…...

linux中playbook的控制语句

本章主要介绍 playbook中的控制语句。 使用 when 判断语句 block-rescue判断 循环语句 一个play中可以包含多个task&#xff0c;如果不想所有的task全部执行&#xff0c;可以设置只有满足某个 条件才执行这个task&#xff0c;不满足条件则不执行此task。本章主要讲解when 和 …...

MongoDB介绍

一、MongoDB介绍 1.1 mongoDB介绍 MongoDB 是由C语言编写的&#xff0c;是一个基于分布式文件存储的开源数据库系统。 在高负载的情况下&#xff0c;添加更多的节点&#xff0c;可以保证服务器性能。 MongoDB 旨在为WEB应用提供可扩展的高性能数据存储解决方案。 MongoDB …...

再看参数校验

作者简介&#xff1a;大家好&#xff0c;我是smart哥&#xff0c;前中兴通讯、美团架构师&#xff0c;现某互联网公司CTO 联系qq&#xff1a;184480602&#xff0c;加我进群&#xff0c;大家一起学习&#xff0c;一起进步&#xff0c;一起对抗互联网寒冬 写一个接口&#xff0c…...

计算机存储术语: 扇区,磁盘块,页

扇区(sector) 硬盘的读写以扇区为基本单位。磁盘上的每个磁道被等分为若干个弧段&#xff0c;这些弧段称之为扇区。硬盘的物理读写以扇区为基本单位。通常情况下每个扇区的大小是 512 字节。linux 下可以使用 fdisk -l 了解扇区大小&#xff1a; $ sudo /sbin/fdisk -l Disk …...

解决IDEA编译/启动报错:Abnormal build process termination

报错信息 报错信息如下&#xff1a; Abnormal build process termination: "D:\Software\Java\jdk\bin\java" -Xmx3048m -Djava.awt.headlesstrue -Djava.endorsed.dirs\"\" -Djdt.compiler.useSingleThreadtrue -Dpreload.project.path………………很纳…...

Jetpack DataStore

文章目录 Jetpack DataStore概述DataStore 对比 SP添加依赖库Preferences DataStore路径创建 Preferences DataStore获取数据保存数据修改数据删除数据清除全部数据 Proto DataStore配置AndroidStudio安装插件配置proto文件创建序列化器 创建 Proto DataStore获取数据保存数据修…...

在Portainer创建Nginx容器并部署Web静态站点实现公网访问

&#x1f525;博客主页&#xff1a; 小羊失眠啦. &#x1f3a5;系列专栏&#xff1a;《C语言》 《数据结构》 《Linux》《Cpolar》 ❤️感谢大家点赞&#x1f44d;收藏⭐评论✍️ 前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;…...

泛微e-cology XmlRpcServlet文件读取漏洞复现

漏洞介绍 泛微新一代移动办公平台e-cology不仅组织提供了一体化的协同工作平台,将组织事务逐渐实现全程电子化,改变传统纸质文件、实体签章的方式。泛微OA E-Cology 平台XmRpcServlet接口处存在任意文件读取漏洞&#xff0c;攻击者可通过该漏洞读取系统重要文件 (如数据库配置…...

当下流行的直播技术demo演示

nginx-http-flv-module&#xff08;更新不是很频繁&#xff09; SRS: https://ossrs.net/lts/zh-cn/&#xff08;独立官网&#xff0c;目前最新稳定版version5&#xff09; 基于SRS搭建直播demo演示&#xff1a; 一、搭建流媒体服务器 参见官网&#xff1a;https://ossrs.ne…...

Zabbix自动发现并注册已安装agent的主机

先在被监控主机上安装好zabbix-agent 然后登录zabbix网页 点击发现动作后会出现第三步 然后编辑操作&#xff0c;发现后加入到主机组群 然后编辑发现规则 然后就可以在主机列表中看到被发现的主机。...

Jtti:linux搭建开源ldap服务器的方法

搭建开源LDAP服务器是一种用于集中管理用户身份认证和授权信息的方法。在Linux系统上&#xff0c;OpenLDAP是一个流行的开源LDAP实现&#xff0c;可以用于搭建LDAP服务器。以下是搭建OpenLDAP服务器的基本步骤&#xff1a; 步骤一&#xff1a;安装OpenLDAP 安装OpenLDAP软件包&…...

Gazebo GUI模型编辑器

模型编辑器 现在我们将构建我们的简单机器人。我们将制作一个轮式车辆&#xff0c;并添加一个传感器&#xff0c;使我们能够让机器人跟随一个斑点&#xff08;人&#xff09;。 模型编辑器允许我们直接在图形用户界面 &#xff08;GUI&#xff09; 中构建简单的模型。对于更复…...

pycharm运行正常,但命令行执行提示module不存在的多种解决方式

问题描述 在执行某个测试模块时出现提示&#xff0c;显示自定义模块data不存在&#xff0c;但是在PyCharm下运行正常。错误信息如下&#xff1a; Traceback (most recent call last):File "/run/channelnterface-autocase/testcases/test_chanel_detail.py", line 2…...

GBASE南大通用GBase 8a ODBC的安装文件

GBASE南大通用GBase 8a ODBC 体系结构是基于五个组件&#xff0c;在下图中所示&#xff1a; GBase 8a ODBC 体系结构图  应用 应用是通过调用 ODBC API 实现对 GBase 数据访问的程序。应用使用标准的 ODBC 调用与驱动程序管理器通信。应用并不关心数据存储在哪里&#xff…...

重新配置torch1.8 cuda11.1 torchtext0.9.0虚拟Pytorch开发环境

这里写目录标题 起因发现选择安装cuda 11.1核对下自己的显卡是否支持下载该版本的CUDACUDA下载地址CUDA安装过程 在anaconda中创建一个虚拟环境1.以下是环境的配置过程2.查看虚拟环境列表3.激活虚拟环境 安装torch和torchtext包的过程1.输入下面这句代码&#xff0c;就可以直接…...

【动画图解】一次理清九大排序算法!面试官问到再也不慌!

排序算法 交换排序 冒泡排序快速排序 插入排序 直接插入排序希尔排序 选择排序 简单选择排序堆排序 归并排序基数排序桶排序 一、冒泡排序 冒泡排序是一种简单的交换排序算法&#xff0c;以升序排序为例&#xff0c;其核心思想是&#xff1a; 从第一个元素开始&#xff0c…...

组播地址段及其作用

作用 组播(Multicast)传输:在发送者和每一接收者之间实现点对多点网络连接。如果一台发送者同时给多个的接收者传输相同的数据&#xff0c;也只需复制一份的相同数据包。它提高了数据传送效率。减少了骨干网络出现拥塞的可能性。 地址段 组播协议的地址在 IP 协议中属于 D 类…...

Vue+ElementUI前端添加展开收起搜索框按钮

1、搜索框添加判断 v-if"advanced" <el-form-item label"创建日期" v-if"advanced"><el-date-pickerv-model"daterangeLedat"size"small"style"width: 240px"value-format"yyyy-MM-dd"type&q…...

C++_核心编程_多态案例二-制作饮品

#include <iostream> #include <string> using namespace std;/*制作饮品的大致流程为&#xff1a;煮水 - 冲泡 - 倒入杯中 - 加入辅料 利用多态技术实现本案例&#xff0c;提供抽象制作饮品基类&#xff0c;提供子类制作咖啡和茶叶*//*基类*/ class AbstractDr…...

Appium+python自动化(十六)- ADB命令

简介 Android 调试桥(adb)是多种用途的工具&#xff0c;该工具可以帮助你你管理设备或模拟器 的状态。 adb ( Android Debug Bridge)是一个通用命令行工具&#xff0c;其允许您与模拟器实例或连接的 Android 设备进行通信。它可为各种设备操作提供便利&#xff0c;如安装和调试…...

Vue3 + Element Plus + TypeScript中el-transfer穿梭框组件使用详解及示例

使用详解 Element Plus 的 el-transfer 组件是一个强大的穿梭框组件&#xff0c;常用于在两个集合之间进行数据转移&#xff0c;如权限分配、数据选择等场景。下面我将详细介绍其用法并提供一个完整示例。 核心特性与用法 基本属性 v-model&#xff1a;绑定右侧列表的值&…...

第一篇:Agent2Agent (A2A) 协议——协作式人工智能的黎明

AI 领域的快速发展正在催生一个新时代&#xff0c;智能代理&#xff08;agents&#xff09;不再是孤立的个体&#xff0c;而是能够像一个数字团队一样协作。然而&#xff0c;当前 AI 生态系统的碎片化阻碍了这一愿景的实现&#xff0c;导致了“AI 巴别塔问题”——不同代理之间…...

Psychopy音频的使用

Psychopy音频的使用 本文主要解决以下问题&#xff1a; 指定音频引擎与设备&#xff1b;播放音频文件 本文所使用的环境&#xff1a; Python3.10 numpy2.2.6 psychopy2025.1.1 psychtoolbox3.0.19.14 一、音频配置 Psychopy文档链接为Sound - for audio playback — Psy…...

Ascend NPU上适配Step-Audio模型

1 概述 1.1 简述 Step-Audio 是业界首个集语音理解与生成控制一体化的产品级开源实时语音对话系统&#xff0c;支持多语言对话&#xff08;如 中文&#xff0c;英文&#xff0c;日语&#xff09;&#xff0c;语音情感&#xff08;如 开心&#xff0c;悲伤&#xff09;&#x…...

vue3+vite项目中使用.env文件环境变量方法

vue3vite项目中使用.env文件环境变量方法 .env文件作用命名规则常用的配置项示例使用方法注意事项在vite.config.js文件中读取环境变量方法 .env文件作用 .env 文件用于定义环境变量&#xff0c;这些变量可以在项目中通过 import.meta.env 进行访问。Vite 会自动加载这些环境变…...

DeepSeek 技术赋能无人农场协同作业:用 AI 重构农田管理 “神经网”

目录 一、引言二、DeepSeek 技术大揭秘2.1 核心架构解析2.2 关键技术剖析 三、智能农业无人农场协同作业现状3.1 发展现状概述3.2 协同作业模式介绍 四、DeepSeek 的 “农场奇妙游”4.1 数据处理与分析4.2 作物生长监测与预测4.3 病虫害防治4.4 农机协同作业调度 五、实际案例大…...

【MATLAB代码】基于最大相关熵准则(MCC)的三维鲁棒卡尔曼滤波算法(MCC-KF),附源代码|订阅专栏后可直接查看

文章所述的代码实现了基于最大相关熵准则(MCC)的三维鲁棒卡尔曼滤波算法(MCC-KF),针对传感器观测数据中存在的脉冲型异常噪声问题,通过非线性加权机制提升滤波器的抗干扰能力。代码通过对比传统KF与MCC-KF在含异常值场景下的表现,验证了后者在状态估计鲁棒性方面的显著优…...

从面试角度回答Android中ContentProvider启动原理

Android中ContentProvider原理的面试角度解析&#xff0c;分为​​已启动​​和​​未启动​​两种场景&#xff1a; 一、ContentProvider已启动的情况 1. ​​核心流程​​ ​​触发条件​​&#xff1a;当其他组件&#xff08;如Activity、Service&#xff09;通过ContentR…...