Java 算法篇-深入了解二分查找法
🔥博客主页: 小扳_-CSDN博客
❤感谢大家点赞👍收藏⭐评论✍


目录
1.0 二分查找法的说明
2.0 二分查找实现的多种版本
2.1 二分查找的基础版本
2.2 二分查找的改动版本
2.3 二分查找的平衡版本
2.4 二分查找的官方版本
3.0 二分查找的应用
1.0 二分查找法的说明
二分查找法(Binary Search)是一种在有序数组或有序列表中查找特定元素的搜索算法。其基本思想是将数组或列表分成两部分,取中间位置的元素进行比较,若该元素等于目标值,则查找成功;若该元素大于目标值,则在左半部分继续查找;若该元素小于目标值,则在右半部分继续查找。不断重复这个过程,直到找到目标值或查找范围缩小到只剩下一个元素为止。
需要重点注意的是,使用二分查找的前提必须是数组是有序的或者列表是有序的。
2.0 二分查找实现的多种版本
基本来说可以分为基础版本和改动版本、平衡版、官方版本。
2.1 二分查找的基础版本
先来讲讲具体的实现吧,需要一个有序的数组 arr[] 或者有序列表,还有拿到需要查找的目标元素 int target。
需要定义一下三种变量:
第一种,int left ;一开始记录着是最左边的元素的索引,即为 0.
第二种,int right;一开始记录着是最右边的元素的索引,即为 array.length - 1.
第三种,int mid;记录着是中间的元素的索引,即为(left + right)>>> 1;
接着先要用 arr[mid] 的元素与 target 进行对比,这时候就会有三种情况,分别做不同的处理,假如 if(arr[mid] < target ),中间的元素小于目标元素时,要对 left 进行 left = mid + 1处理,假如 if(arr[mid] > target ),中间的元素大于目标元素时,要对 right 进行 right = mid - 1处理,假如 if(arr[mid] = target ),这时候就找到了目标元素了,直接返回 mid ,因此这是一个循环的过程,不断缩小范围来寻找目标元素,这一切都需要满足 left <= right 这个条件。
具体代码实现如下:
public class BinarySearch {public static void main(String[] args) {int[] arr = {1,3,5,7,9,11};int target = 3;System.out.println(search(arr, target));}public static int search(int[] arr, int target){int left = 0;int right = arr.length - 1;while (left <= right){int mid = (left + right) >>> 1;if (arr[mid] < target){left = mid + 1;} else if (target < arr[mid]) {right = mid - 1;}else {return mid;}}return -1;} }运行结果如下:
目标元素3的索引为1,补充一下,若没有找到的话,这里定义返回为 -1 。
2.2 二分查找的改动版本
这个版本在基础版本的基础上进行了三点改动:
第一点;int right;一开始记录着是最右边的元素的索引,即为 array.length 。
注意,在基础版本中是需要减1的,而这里直接取元素个数,当然我们都知道这个会出现越界情况,所以才会有第二点改动 。
第二点;这一切都需要满足 left < right 这个条件。
这基础版本中循环条件是需要 <= 的条件,这里就不需要了,来分析一下为什么呢?
原因就在第一点,在 right 索引下的元素是不可取的,重点在<不可取>,仔细品味一下,无论right 在之后的循环中得到的所有索引都是不可取到的元素。
第三点;假如 if(arr[mid] > target ),中间的元素大于目标元素时,要对 right 进行 right = mid 处理。
具体代码实现如下:
public class NewBinarySearch {public static void main(String[] args) {int[] arr = {1,3,5,7,9,11};int target = 3;System.out.println(search(arr, target));}public static int search(int[] arr, int target) {int left = 0;int right = arr.length;while (left < right) {int mid = (left + right) >>> 1;if (arr[mid] < target) {left = mid + 1;} else if (target < arr[mid]) {right = mid;} else {return mid;}}return -1;} }运行结果如下:
2.3 二分查找的平衡版本
相对比与第一、两种,这个版本的效率会更高一点。这种版本的思路就是将范围不断缩小为1,然后获取 left 索引下的元素,来判断是否等于目标元素。
具体代码如下:
public class NewBinarySearch {public static void main(String[] args) {int[] arr = {1,3,5,7,9,11};int target = 3;System.out.println(search(arr, target));}public static int search (int[] arr, int target){int left = 0;int right = arr.length;while (1 < right - left){int mid = (left + right) >>> 1;if (target < arr[mid]){right = mid;} else {left = mid;}}if (arr[left] == target){return left;}else {return -1;}} }运行结果如下:
2.4 二分查找的官方版本
直接来看原代码:
来分析一下,从总体来看,官方的二分查找的实现跟第一种的基本版本是大致相同的,有一点跟基础版本的不同的是,就是返回值。在基础版本中,如果找不到就返回 -1,而这里返回的是 -(low + 1),接下来具体讲解一下。
第一点,low 代表的是插入点,这个值跟 left 的值是一样的。
第二点,关于负数的说法,一般来说找不到的元素时,会返回负数。
具体代码的实现:
public class NewBinarySearch {public static void main(String[] args) {int[] arr = {1,3,5,7,9,11};int target = 2;System.out.println(search(arr, target));}public static int search(int[] arr, int target) {int left = 0;int right = arr.length - 1;while (left <= right) {int mid = (left + right) >>> 1;if (arr[mid] < target) {left = mid + 1;} else if (target < arr[mid]) {right = mid - 1;} else {return mid;}}return -(left + 1);} }运行结果如下:
来算一下,我们知道 2 在数组中是不存在的,插入点为 1 ,则-(1+1)== -2,验证了是符合的结果的。
3.0 二分查找的应用
给出下列数组 int[] arr {1,2,3,3,3,3,5,6,7} 要求返回目标元素3的起始位置与结束位置。
实现的思路:先找起始位置,首先得先找到目标元素的索引,之后得往左边去找。找结束位置也是同理,首先得先找到目标元素的索引,之后得往右边去找。
代码如下:
public class NewBinarySearch {public static void main(String[] args) {int[] arr = {1,2,3,3,3,3,5,6,7};int target = 3;System.out.print(findLeft(arr, 3)+" ");System.out.println(findRight(arr, 3));}public static int findLeft(int[] arr,int target){int left = 0;int right = arr.length - 1;int sign = -1;while (left <= right){int mid = (left + right) >>> 1;if (arr[mid] < target){left = mid + 1;} else if (target < arr[mid]) {right = mid - 1;}else {sign = mid;right = mid - 1;}}return sign;}public static int findRight(int[] arr, int target){int left = 0;int right = arr.length - 1;int sign = -1;while (left <= right){int mid = (left + right) >>> 1;if (arr[mid] < target){left = mid + 1;} else if (target < arr[mid]) {right = mid - 1;}else {sign = mid;left = mid + 1;}}return sign;} }运行结果如下:
相关文章:
Java 算法篇-深入了解二分查找法
🔥博客主页: 小扳_-CSDN博客 ❤感谢大家点赞👍收藏⭐评论✍ 目录 1.0 二分查找法的说明 2.0 二分查找实现的多种版本 2.1 二分查找的基础版本 2.2 二分查找的改动版本 2.3 二分查找的平衡版本 2.4 二分查找的官方版本 3.0 二分查找的应用 1…...
Data-Centric Financial Large Language Models
本文是LLM系列文章,针对《Data-Centric Financial Large Language Models》的翻译。 以数据为中心的大语言金融模型 摘要1 引言2 背景3 方法4 实验5 结论和未来工作 摘要 大型语言模型(LLM)有望用于自然语言任务,但在直接应用于…...
【HarmonyOS】服务卡片 API6 JSUI跳转不同页面并携带参数
【关键字】 服务卡片、卡片跳转不同页面、卡片跳转页面携带参数 【写在前面】 本篇文章主要介绍开发服务卡片时,如何实现卡片点击跳转不同页面,并携带动态参数到js页面。在此篇文章“服务卡片 API6 JSUI跳转不同页面”中说明了如果跳转不同页面…...
SQL server数据库端口访问法
最近数据库连接,也是无意中发现了这个问题,数据库可根据端口来连接 网址:yii666.com< 我用的是sql2014测试的,在安装其他程序是默认安装了sql(sql的tcp/ip端口为xxx),服务也不相同,但是由于比较不全,我…...
深孔枪钻厂家,科研管理系统思路
序号 名称 参数及技术指标 (一)系统性能要求 1.系统界面:支持中英文界面自由切换。 2. 系统兼容性:支持主流浏览器,如:IE11 以上、 360 安全浏览器、Firefox、Google Ch…...
【论文阅读笔记】GLM-130B: AN OPEN BILINGUAL PRE-TRAINEDMODEL
Glm-130b:开放式双语预训练模型 摘要 我们介绍了GLM-130B,一个具有1300亿个参数的双语(英语和汉语)预训练语言模型。这是一个至少与GPT-3(达芬奇)一样好的100b规模模型的开源尝试,并揭示了如何成功地对这种规模的模型进行预训练。在这一过程中࿰…...
Object常用方法
Object常用方法目录 1. equals(Object obj): 2. toString(): 3. hashCode(): 4. getClass(): 5. notify() 和 notifyAll(): 6. wait() 和 wait(long timeout): 7. clone(): 8. fina…...
【VR开发】【Unity】【VRTK】2-关于VR的基础知识
【概述】 在VRTK的实操讲解之前,本篇先介绍几个重要的VR认识。 【VR对各个行业的颠覆】 如果互联网几乎把所有行业都重做了一遍,VR在接下来的几年很可能再把现有的行业都重做一遍,包括但不限于教育,房地产,零售&…...
jeecg-uniapp 转成小程序的过程 以及报错 uniapp点击事件
uniapp 点击事件 tap: 单击事件 confirm: 回车事件 blur:失去焦点事件 touchstart: 触摸开始事件 touchmove: 触摸移动事件。 touchend: 触摸结束事件。 longpress: 长按事件。 input: 输入框内容变化事件。 change: 表单元素值变化事件。 submit: 表单提交事件。 scroll: 滚动…...
Django的静态文件目录(路径)如何配置?
通常用下面的三条语句配置Django的静态文件目录 STATICFILES_DIRS [os.path.join(BASE_DIR, static)] STATIC_URL /static/ STATIC_ROOT os.path.join(BASE_DIR, /static)那么这三条语句分别的作用是什么呢? 请参考博文 https://blog.csdn.net/wenhao_ir/articl…...
函数应用(MySQL)
--数值类函数 --绝对值 select abs(-1) --seiling ceil 向上取整 select ceil(1.1) --floor 向下取整 select floor(1.9); --四舍五入 select round(1.17, 1); --rand 随机数 select rand(rand()*1000); --字符串函数 utf8mb3 utfmb4 select length(小三) --查找字符数…...
数据分析过程中,发现数值缺失,怎么办?
按照数据缺失机制,数据分析过程中,我们可以将其分为以下几类: (1)完全随机缺失(MCAR):所缺失的数据发生的概率既与已观察到的数据无关,也与未观察到的数据无关。 &#x…...
Vue3.0 toRef toRefs :VCA模式
简介 作用: 创建一个ref对象,其value值指向另一个对象中的某个属性 语法: const name toRef(person, name) 应用: 要将响应式对象中的某个属性单独供应给外部使用时 扩展: toRefs与toRef功能一致,但可…...
VS Code提取扩展时出错。XHR failed
需求:想要在扩展中心下载插件,发现报错 原因:vs code之前设置了代理,需要删除即可...
大模型需要哪类服务器
大模型需要高性能的服务器,以支持大规模的计算和存储需求。一般来说,大模型需要以下类型的服务器: 大型机:大型机可以提供强大的计算能力,适合处理大规模的数据和复杂的计算任务。 GPU服务器:GPU服务器可以…...
Java进阶(List)——面试时List常见问题解读 结合源码分析
前言 List、Set、HashMap作为Java中常用的集合,需要深入认识其原理和特性。 本篇博客介绍常见的关于Java中List集合的面试问题,结合源码分析题目背后的知识点。 关于的Set的博客文章如下: Java进阶(Set)——面试时…...
0基础学习PyFlink——个数滑动窗口(Sliding Count Windows)
大纲 滑动(Sliding)和滚动(Tumbling)的区别样例窗口为2,滑动距离为1窗口为3,滑动距离为1窗口为3,滑动距离为2窗口为3,滑动距离为3 完整代码参考资料 在 《0基础学习PyFlink——个数…...
vue3+ts 提取公共方法
因为好多页面都会使用到这个效验规则,封装一个校检规则,方便维护 封装前 封装后...
C++ ->
C -> 是访问类或结构体对象的成员的运算符 注意这里不是直接的访问.是用于访问指向对象的指针的成员 下面的代码可以很好的理解如下: #include<iostream>using namespace std;class Func{public:int i,j;void myFunc(){cout<<"i"<&l…...
VR全景在医院的应用:缓和医患矛盾、提升医院形象
医患关系一直以来都是较为激烈的,包括制度的不完善、医疗资源紧张等问题也时有存在,为了缓解医患矛盾,不仅要提升患者以及家属对于医院的认知,还需要完善医疗制度,提高医疗资源的配置效率,提高服务质量。 因…...
RestClient
什么是RestClient RestClient 是 Elasticsearch 官方提供的 Java 低级 REST 客户端,它允许HTTP与Elasticsearch 集群通信,而无需处理 JSON 序列化/反序列化等底层细节。它是 Elasticsearch Java API 客户端的基础。 RestClient 主要特点 轻量级ÿ…...
MMaDA: Multimodal Large Diffusion Language Models
CODE : https://github.com/Gen-Verse/MMaDA Abstract 我们介绍了一种新型的多模态扩散基础模型MMaDA,它被设计用于在文本推理、多模态理解和文本到图像生成等不同领域实现卓越的性能。该方法的特点是三个关键创新:(i) MMaDA采用统一的扩散架构…...
Python实现prophet 理论及参数优化
文章目录 Prophet理论及模型参数介绍Python代码完整实现prophet 添加外部数据进行模型优化 之前初步学习prophet的时候,写过一篇简单实现,后期随着对该模型的深入研究,本次记录涉及到prophet 的公式以及参数调优,从公式可以更直观…...
MODBUS TCP转CANopen 技术赋能高效协同作业
在现代工业自动化领域,MODBUS TCP和CANopen两种通讯协议因其稳定性和高效性被广泛应用于各种设备和系统中。而随着科技的不断进步,这两种通讯协议也正在被逐步融合,形成了一种新型的通讯方式——开疆智能MODBUS TCP转CANopen网关KJ-TCPC-CANP…...
Android15默认授权浮窗权限
我们经常有那种需求,客户需要定制的apk集成在ROM中,并且默认授予其【显示在其他应用的上层】权限,也就是我们常说的浮窗权限,那么我们就可以通过以下方法在wms、ams等系统服务的systemReady()方法中调用即可实现预置应用默认授权浮…...
【学习笔记】深入理解Java虚拟机学习笔记——第4章 虚拟机性能监控,故障处理工具
第2章 虚拟机性能监控,故障处理工具 4.1 概述 略 4.2 基础故障处理工具 4.2.1 jps:虚拟机进程状况工具 命令:jps [options] [hostid] 功能:本地虚拟机进程显示进程ID(与ps相同),可同时显示主类&#x…...
算法笔记2
1.字符串拼接最好用StringBuilder,不用String 2.创建List<>类型的数组并创建内存 List arr[] new ArrayList[26]; Arrays.setAll(arr, i -> new ArrayList<>()); 3.去掉首尾空格...
Android第十三次面试总结(四大 组件基础)
Activity生命周期和四大启动模式详解 一、Activity 生命周期 Activity 的生命周期由一系列回调方法组成,用于管理其创建、可见性、焦点和销毁过程。以下是核心方法及其调用时机: onCreate() 调用时机:Activity 首次创建时调用。…...
LeetCode - 199. 二叉树的右视图
题目 199. 二叉树的右视图 - 力扣(LeetCode) 思路 右视图是指从树的右侧看,对于每一层,只能看到该层最右边的节点。实现思路是: 使用深度优先搜索(DFS)按照"根-右-左"的顺序遍历树记录每个节点的深度对于…...
基于 TAPD 进行项目管理
起因 自己写了个小工具,仓库用的Github。之前在用markdown进行需求管理,现在随着功能的增加,感觉有点难以管理了,所以用TAPD这个工具进行需求、Bug管理。 操作流程 注册 TAPD,需要提供一个企业名新建一个项目&#…...




