二分查找-java

二分查找-java

  • 二分查找
    • 基础版
    • 改动版
    • 平衡版
  • 二分查找高级用法
    • LeftMost
      • 01
      • 02
    • RightMost
      • 01
      • 02
    • LeftMost和RightMost的方式二的高级用法

二分查找

基础版

arr是待查找升序数组,target是待查找元素

基础版的left和right两个所指向的元素都是待查找值

public static int binarySearchBasic(int[] arr, int target) {int left = 0, right = arr.length - 1; //设置指针和初始值while (left <= right) { //left 到 right 中间有东西int middle = (left + right) / 2;if (target < arr[middle]) { //目标在左边right = middle - 1;} else if (arr[middle] < target) { //目标在右边left = middle + 1;} else {   //找到了return middle;}}return -1;  //没找到
}

两个改进点:

  • int middle = (left + right) / 2;
    //改进后,使用无符号右移运算符
    int middle = (left + right) >>> 1;
    
    • 如果数组数据过大,(left + right) / 2的计算结果可能就超过int的表示范围,会由正变负
    • (left + right) >>> 1,不会出现这种问题
  • 返回值为-1,没有什么特殊意义。可以根据返回值算出插入点

    • 参考jdk的Arrays工具类
    • 返回值改为"-(left + 1)"。left可以表示插入点,这里为了避免索引0位置产生歧义,返回加一之后的相反数
    • 插入点计算方法是:“Math.abs(返回值+1)”

改动版

left指向的还是待查找值

right只是作为边界,不指向待查找值

public static int binarySearchAlternative(int[] arr, int target) {int left = 0, right = arr.length; //第一处while(left < right){	//第二处int middle = (left + right) >>> 1;if(target < arr[middle]){right = middle; //第三处}else if(arr[middle] < target){left = middle + 1;}else{return middle;}}return -(left + 1);	//如果没有该值,返回该值插入点加一的相反数
}

平衡版

基础版和改动版对于while循环中选择语句的执行次数不平衡。

​ 具体含义是,如果查找的数是不存在的,且当该值小于数组最小值和大于数组最大值的时候执行的比较次数是不一样的

public static int binarySearchBalance(int[] arr, int target) {int left = 0, right = arr.length;while (1 < right - left) {   //范围内待查找的元素个数 > 1 时int middle = (left + right) >>> 1;if (target < arr[middle]) { //目标在左边right = middle;} else { //目标在middle 或者 右边left = middle;}}return (target == arr[left]) ? left : -1;
}

二分查找高级用法

LeftMost

01

查找升序数组,某个重复元素最左边的位置的索引。不存在返回-1

public static int binarySearchLeftmost1(int[] arr, int target) {int left = 0, right = arr.length - 1;int candidate = -1;while(left <= right){int middle = (left + right) >>> 1;if(target < arr[middle]){right = middle - 1;}else if(arr[middle] < target){left = middle + 1;}else{//更改候选位置candidate = middle;right = middle - 1;}}return candidate;
}

02

查找升序数组,如果目标值存在目标值索引位置,如果目标值重复存在,返回最左边的索引

​ 如果目标值不存在,返回大于目标值最左边的索引位置

即,返回大于等于目标值的最左边位置的索引

public static int binarySearchLeftmost2(int[] arr, int target) {int left = 0, right = arr.length - 1;while(left <= right){int middle = (left + right) >>> 1;if(target <= arr[middle]){right = middle - 1;}else if(arr[middle] < target){left = middle + 1;}}return left;
}

RightMost

01

查找升序数组,某个重复元素最右边的位置的索引。不存在返回-1

public static int binarySearchRightmost1(int[] arr, int target) {int left = 0, right = arr.length - 1;int candidate = -1;while(left <= right){int middle = (left + right) >>> 1;if(target < arr[middle]){right = middle - 1;}else if(arr[middle] < target){left = middle + 1;}else{//更改候选位置candidate = middle;left = midddle + 1;}}return candidate;
}

02

查找升序数组,如果目标值存在目标值索引位置,如果目标值重复存在,返回最右边的索引

​ 如果目标值不存在,返回小于目标值最右边的索引位置

即,返回小于等于目标值的最右边位置的索引

public static int binarySearchRightmost2(int[] arr, int target) {int left = 0, right = arr.length - 1;while (left <= right) {int middle = (left + right) >>> 1;if (target < arr[middle]) {right = middle - 1;} else {left = middle + 1;}}return left - 1;
}

LeftMost和RightMost的方式二的高级用法

几个名词

image-20221125174155058

范围查询

基础版leftmost和基础版rightmost应用

  • 查询 x < 4 x \lt 4 x<4 0.. l e f t m o s t ( 4 ) − 1 0 .. leftmost(4) - 1 0..leftmost(4)1
  • 查询 x ≤ 4 x \leq 4 x4 0.. r i g h t m o s t ( 4 ) 0 .. rightmost(4) 0..rightmost(4)
  • 查询 4 < x 4 \lt x 4<x,$rightmost(4) + 1 … \infty $
  • 查询 4 ≤ x 4 \leq x 4x l e f t m o s t ( 4 ) . . ∞ leftmost(4) .. \infty leftmost(4)..∞
  • 查询 4 ≤ x ≤ 7 4 \leq x \leq 7 4x7 l e f t m o s t ( 4 ) . . r i g h t m o s t ( 7 ) leftmost(4) .. rightmost(7) leftmost(4)..rightmost(7)
  • 查询 4 < x < 7 4 \lt x \lt 7 4<x<7 r i g h t m o s t ( 4 ) + 1.. l e f t m o s t ( 7 ) − 1 rightmost(4)+1 .. leftmost(7)-1 rightmost(4)+1..leftmost(7)1

求排名 l e f t m o s t ( t a r g e t ) + 1 leftmost(target) + 1 leftmost(target)+1

索引从0开始, 排名是从1开始的

  • t a r g e t target target 可以不存在,如: l e f t m o s t ( 5 ) + 1 = 6 leftmost(5)+1 = 6 leftmost(5)+1=6
  • t a r g e t target target 也可以存在,如: l e f t m o s t ( 4 ) + 1 = 3 leftmost(4)+1 = 3 leftmost(4)+1=3

求前任(predecessor) l e f t m o s t ( t a r g e t ) − 1 leftmost(target) - 1 leftmost(target)1

前任的索引

  • l e f t m o s t ( 3 ) − 1 = 1 leftmost(3) - 1 = 1 leftmost(3)1=1,前任 a 1 = 2 a_1 = 2 a1=2
  • l e f t m o s t ( 4 ) − 1 = 1 leftmost(4) - 1 = 1 leftmost(4)1=1,前任 a 1 = 2 a_1 = 2 a1=2

求后任(successor) r i g h t m o s t ( t a r g e t ) + 1 rightmost(target)+1 rightmost(target)+1

后任的索引

  • r i g h t m o s t ( 5 ) + 1 = 5 rightmost(5) + 1 = 5 rightmost(5)+1=5,后任 a 5 = 7 a_5 = 7 a5=7
  • r i g h t m o s t ( 4 ) + 1 = 5 rightmost(4) + 1 = 5 rightmost(4)+1=5,后任 a 5 = 7 a_5 = 7 a5=7

求最近邻居

  • 前任和后任距离更近者

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/618794.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【1000个GDB技巧之】如何在远端服务器打开通过vscode动态观测Linux内核实战篇?

Step: 配置ssh的服务端host &#xff08;也可以直接在vscode中配置&#xff0c;忽略&#xff09; 主要步骤&#xff1a;在~/.ssh/config中添加服务端的host&#xff0c;以便vscode的remote中能够登录 详细配置过程参考兄弟篇文章&#xff1a;ssh config如何配置用host名替代ro…

【Linux】阿里云ECS搭建lnmp和lamp集群

搭建LNMP&#xff08;Linux Nginx MySQL PHP&#xff09;或LAMP&#xff08;Linux Apache MySQL PHP&#xff09;集群 创建ECS实例&#xff1a; 在阿里云控制台创建多个ECS实例&#xff0c;选择相应的操作系统和配置&#xff0c;确保这些实例在同一VPC网络内&#xff0c;…

系统架构最佳实践 -- 金融企业的资损问题介绍

什么是资损 资损通常来讲是指支付场景下的资金损失&#xff0c;这里可以从两个维度看 用户角度&#xff1a;多扣用户款导致用户资金损失&#xff0c;此问题一般需要通过客服等渠道反馈&#xff0c;可以把多的钱退给用户&#xff0c;但是很大程度上损失了用户体验&#xff1b; …

ssh爆破服务器的ip-疑似肉鸡

最近发现自己的ssh一直有一些人企图使用ssh暴力破解的方式进行密码破解.就查看了一下,真是网络安全太可怕了. 大家自己的服务器密码还是要设置好,管好,做好最基本的安全措施,不然最后只能沦为肉鸡. ssh登陆日志可以在/var/log下看到,ubuntu的话为auth.log,centos为secure文件 查…

【算法】回溯:与递归,dfs的同质与分别,剪枝与恢复现场的详细理解,n皇后的回溯解法及算法复杂度分析。

目录 ​编辑 1.什么是回溯 2.关于剪枝 3.关于恢复现场 4.题目&#xff1a;二叉树的所有路径&#xff08;凸显恢复现场&#xff1a;切实感受回溯与深搜&#xff09; 问题分析 ①函数设置为&#xff1a;void Dfs(root) ②函数设置为&#xff1a;void Dfs(root,path) 解题思想&…

微信小程序 发送消息 Token校验失败,请检查确认

如上图&#xff0c;文档中说的是 开发者通过检验 signature 对请求进行校验&#xff08;下面有校验方式&#xff09;。若确认此次 GET 请求来自微信服务器&#xff0c;请原样返回 echostr 参数内容&#xff0c;则接入生效&#xff0c;成为开发者成功&#xff0c;否则接入失败。…

深度学习图像处理基础工具——opencv 实战信用卡数字识别

任务 信用卡数字识别 穿插之前学的知识点 形态学操作 模板匹配 等 总体流程与方法 1.有一个模板 2 用轮廓检测把模板中数字拿出来 外接矩形&#xff08;模板和输入图像的大小要一致 &#xff09;3 一系列预处理操作 问题的解决思路 1.分析准备&#xff1a;准备模板&#…

[管理者与领导者-163] :团队管理 - 高效执行力 -1- 高效沟通的架构、关键问题、注意事项

目录 前言&#xff1a;沟通是管理者实施管理最重要的工作 一、人与人沟通模型 1.1 模型 1.2 完整过程 1.3 发送和接受方式 1.4 传输 1.5 关于编码与解码 1.6 反馈 1.7 沟通中常见问题 二、管理者如何提高沟通的效率 2.1 为什么管理者布置任务后&#xff0c;总有人…

数据仓库—维度建模—维度表设计

维度表 维度表(Dimension Table)是数据仓库中描述业务过程中各种维度信息的表,用于提供上下文和描述性信息,以丰富事实数据的分析 维度表是维度建模的灵魂所在,在维度表设计中碰到的问题(比如维度变化、维度层次、维度一致性、维度整合和拆分等)都会直接关系到维度建模…

pyqt和opencv结合01:读取图像、显示

在这里插入图片描述 1 、opencv读取图像用于pyqt显示 # image cv2.imread(file_path)image cv2.cvtColor(image, cv2.COLOR_BGR2RGB)# 将图像转换为 Qt 可接受的格式height, width, channel image.shapebytes_per_line 3 * widthq_image QImage(image.data, width, hei…

OLTP 与 OLAP 系统说明对比和大数据经典架构 Lambda 和 Kappa 说明对比——解读大数据架构(五)

文章目录 前言OLTP 和 OLAPSMP 和 MPPlambda 架构Kappa 架构 前言 本文我们将研究不同类型的大数据架构设计&#xff0c;将讨论 OLTP 和 OLAP 的系统设计&#xff0c;以及有效处理数据的策略包括 SMP 和 MPP 等概念。然后我们将了解经典的 Lambda 架构和 Kappa 架构。 OLTP …

【脚本】多功能Ubuntu临时授予用户sudo权限管理工具

转载请注明出处&#xff1a;小锋学长生活大爆炸[xfxuezhagn.cn] 设计原理和初衷可以看这里&#xff1a;【技巧】Ubuntu临时授予用户sudo权限&#xff0c;并在一定时间后自动撤销_ubuntu jianshao sudo-CSDN博客文章浏览阅读404次。非常实用_ubuntu jianshao sudohttps://blog.c…