二分查找法详解(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种变形)
前言 在之前的博客中,我给大家介绍了最基础的二分查找法(没学的话点我点我!) 今天我将带大家学习二分法的六种变形如何使用,小伙伴们,快来开始今天的学习吧! 文章目录 1,查找第一个…...
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"><!-- 第一个参数为你的单选数组,第二个…...
linux中playbook的控制语句
本章主要介绍 playbook中的控制语句。 使用 when 判断语句 block-rescue判断 循环语句 一个play中可以包含多个task,如果不想所有的task全部执行,可以设置只有满足某个 条件才执行这个task,不满足条件则不执行此task。本章主要讲解when 和 …...
MongoDB介绍
一、MongoDB介绍 1.1 mongoDB介绍 MongoDB 是由C语言编写的,是一个基于分布式文件存储的开源数据库系统。 在高负载的情况下,添加更多的节点,可以保证服务器性能。 MongoDB 旨在为WEB应用提供可扩展的高性能数据存储解决方案。 MongoDB …...
再看参数校验
作者简介:大家好,我是smart哥,前中兴通讯、美团架构师,现某互联网公司CTO 联系qq:184480602,加我进群,大家一起学习,一起进步,一起对抗互联网寒冬 写一个接口,…...
计算机存储术语: 扇区,磁盘块,页
扇区(sector) 硬盘的读写以扇区为基本单位。磁盘上的每个磁道被等分为若干个弧段,这些弧段称之为扇区。硬盘的物理读写以扇区为基本单位。通常情况下每个扇区的大小是 512 字节。linux 下可以使用 fdisk -l 了解扇区大小: $ sudo /sbin/fdisk -l Disk …...
解决IDEA编译/启动报错:Abnormal build process termination
报错信息 报错信息如下: 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静态站点实现公网访问
🔥博客主页: 小羊失眠啦. 🎥系列专栏:《C语言》 《数据结构》 《Linux》《Cpolar》 ❤️感谢大家点赞👍收藏⭐评论✍️ 前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,…...
泛微e-cology XmlRpcServlet文件读取漏洞复现
漏洞介绍 泛微新一代移动办公平台e-cology不仅组织提供了一体化的协同工作平台,将组织事务逐渐实现全程电子化,改变传统纸质文件、实体签章的方式。泛微OA E-Cology 平台XmRpcServlet接口处存在任意文件读取漏洞,攻击者可通过该漏洞读取系统重要文件 (如数据库配置…...
当下流行的直播技术demo演示
nginx-http-flv-module(更新不是很频繁) SRS: https://ossrs.net/lts/zh-cn/(独立官网,目前最新稳定版version5) 基于SRS搭建直播demo演示: 一、搭建流媒体服务器 参见官网:https://ossrs.ne…...
Zabbix自动发现并注册已安装agent的主机
先在被监控主机上安装好zabbix-agent 然后登录zabbix网页 点击发现动作后会出现第三步 然后编辑操作,发现后加入到主机组群 然后编辑发现规则 然后就可以在主机列表中看到被发现的主机。...
Jtti:linux搭建开源ldap服务器的方法
搭建开源LDAP服务器是一种用于集中管理用户身份认证和授权信息的方法。在Linux系统上,OpenLDAP是一个流行的开源LDAP实现,可以用于搭建LDAP服务器。以下是搭建OpenLDAP服务器的基本步骤: 步骤一:安装OpenLDAP 安装OpenLDAP软件包&…...
Gazebo GUI模型编辑器
模型编辑器 现在我们将构建我们的简单机器人。我们将制作一个轮式车辆,并添加一个传感器,使我们能够让机器人跟随一个斑点(人)。 模型编辑器允许我们直接在图形用户界面 (GUI) 中构建简单的模型。对于更复…...
pycharm运行正常,但命令行执行提示module不存在的多种解决方式
问题描述 在执行某个测试模块时出现提示,显示自定义模块data不存在,但是在PyCharm下运行正常。错误信息如下: Traceback (most recent call last):File "/run/channelnterface-autocase/testcases/test_chanel_detail.py", line 2…...
GBASE南大通用GBase 8a ODBC的安装文件
GBASE南大通用GBase 8a ODBC 体系结构是基于五个组件,在下图中所示: GBase 8a ODBC 体系结构图 应用 应用是通过调用 ODBC API 实现对 GBase 数据访问的程序。应用使用标准的 ODBC 调用与驱动程序管理器通信。应用并不关心数据存储在哪里ÿ…...
重新配置torch1.8 cuda11.1 torchtext0.9.0虚拟Pytorch开发环境
这里写目录标题 起因发现选择安装cuda 11.1核对下自己的显卡是否支持下载该版本的CUDACUDA下载地址CUDA安装过程 在anaconda中创建一个虚拟环境1.以下是环境的配置过程2.查看虚拟环境列表3.激活虚拟环境 安装torch和torchtext包的过程1.输入下面这句代码,就可以直接…...
【动画图解】一次理清九大排序算法!面试官问到再也不慌!
排序算法 交换排序 冒泡排序快速排序 插入排序 直接插入排序希尔排序 选择排序 简单选择排序堆排序 归并排序基数排序桶排序 一、冒泡排序 冒泡排序是一种简单的交换排序算法,以升序排序为例,其核心思想是: 从第一个元素开始,…...
组播地址段及其作用
作用 组播(Multicast)传输:在发送者和每一接收者之间实现点对多点网络连接。如果一台发送者同时给多个的接收者传输相同的数据,也只需复制一份的相同数据包。它提高了数据传送效率。减少了骨干网络出现拥塞的可能性。 地址段 组播协议的地址在 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…...
在软件开发中正确使用MySQL日期时间类型的深度解析
在日常软件开发场景中,时间信息的存储是底层且核心的需求。从金融交易的精确记账时间、用户操作的行为日志,到供应链系统的物流节点时间戳,时间数据的准确性直接决定业务逻辑的可靠性。MySQL作为主流关系型数据库,其日期时间类型的…...
OpenLayers 可视化之热力图
注:当前使用的是 ol 5.3.0 版本,天地图使用的key请到天地图官网申请,并替换为自己的key 热力图(Heatmap)又叫热点图,是一种通过特殊高亮显示事物密度分布、变化趋势的数据可视化技术。采用颜色的深浅来显示…...
synchronized 学习
学习源: https://www.bilibili.com/video/BV1aJ411V763?spm_id_from333.788.videopod.episodes&vd_source32e1c41a9370911ab06d12fbc36c4ebc 1.应用场景 不超卖,也要考虑性能问题(场景) 2.常见面试问题: sync出…...
DockerHub与私有镜像仓库在容器化中的应用与管理
哈喽,大家好,我是左手python! Docker Hub的应用与管理 Docker Hub的基本概念与使用方法 Docker Hub是Docker官方提供的一个公共镜像仓库,用户可以在其中找到各种操作系统、软件和应用的镜像。开发者可以通过Docker Hub轻松获取所…...
转转集团旗下首家二手多品类循环仓店“超级转转”开业
6月9日,国内领先的循环经济企业转转集团旗下首家二手多品类循环仓店“超级转转”正式开业。 转转集团创始人兼CEO黄炜、转转循环时尚发起人朱珠、转转集团COO兼红布林CEO胡伟琨、王府井集团副总裁祝捷等出席了开业剪彩仪式。 据「TMT星球」了解,“超级…...
基于Docker Compose部署Java微服务项目
一. 创建根项目 根项目(父项目)主要用于依赖管理 一些需要注意的点: 打包方式需要为 pom<modules>里需要注册子模块不要引入maven的打包插件,否则打包时会出问题 <?xml version"1.0" encoding"UTF-8…...
从零实现STL哈希容器:unordered_map/unordered_set封装详解
本篇文章是对C学习的STL哈希容器自主实现部分的学习分享 希望也能为你带来些帮助~ 那咱们废话不多说,直接开始吧! 一、源码结构分析 1. SGISTL30实现剖析 // hash_set核心结构 template <class Value, class HashFcn, ...> class hash_set {ty…...
HTML前端开发:JavaScript 常用事件详解
作为前端开发的核心,JavaScript 事件是用户与网页交互的基础。以下是常见事件的详细说明和用法示例: 1. onclick - 点击事件 当元素被单击时触发(左键点击) button.onclick function() {alert("按钮被点击了!&…...
分布式增量爬虫实现方案
之前我们在讨论的是分布式爬虫如何实现增量爬取。增量爬虫的目标是只爬取新产生或发生变化的页面,避免重复抓取,以节省资源和时间。 在分布式环境下,增量爬虫的实现需要考虑多个爬虫节点之间的协调和去重。 另一种思路:将增量判…...
微软PowerBI考试 PL300-在 Power BI 中清理、转换和加载数据
微软PowerBI考试 PL300-在 Power BI 中清理、转换和加载数据 Power Query 具有大量专门帮助您清理和准备数据以供分析的功能。 您将了解如何简化复杂模型、更改数据类型、重命名对象和透视数据。 您还将了解如何分析列,以便知晓哪些列包含有价值的数据,…...
