数据结构与算法——Java实现 3.二分查找——Java版

news2024/11/13 20:40:58

放下不切实际的幻想,放下无法更改的过去,行云流水,任其行之

                                                                                                —— 24.8.31

一、二分查找——Java基础版

Java中的API——Arrays.binarySearch(数组,目标值)

返回的结果是插入点的位置

若在目标数组中找不到元素,则返回的是负的(插入该点的位置+1)

+1,是为了避免在第一个位置插入时,返回0与查找元素刚好处在第一个位置重复的这种情况,+1可以分辨这两种情况,观察是否返回的是负数

import java.util.Arrays;

public class demo2BinarySearchJava {
    public static void main(String[] args) {
        int[] arr = {1,2,3,4,5,6,7,8,9,10};
        int target = -1;
        int res = Arrays.binarySearch(arr, target);
        // 找不到时,会返回负的(插入点的位置+1):-(low+1)    +1是为了区分在第一个0位置插入的情况
        System.out.println("res: " + res); // 11
        // 返回点的插入位置用i变量表示就可以
        if(res < 0){
            // Math.abs:绝对值函数
            // 插入点索引insert
            int insert = Math.abs(res+1);
            // 创建数组B
            int[] arrB = new int[arr.length+1];
            // 数组拷贝 被拷贝数组 拷贝位置 目标新数组 拷贝起始位置 拷贝数据的长度
            System.arraycopy(arr,0,arrB,0,insert);
            // 将被插入点位置元素改为插入元素
            arrB[insert] = target;
            // 数组拷贝 将新插入元素后位置的函数插入到插入点位置
            System.arraycopy(arr,insert,arrB,insert+1,arr.length-insert);
            System.out.println(Arrays.toString(arrB));
        }
    }
}

二、二分查找——找到重复元素中元素的位置

1.找到重复元素中最左侧第一个出现元素的位置

当数组中存在多个待查找的元素时,观察寻找最左侧元素的位置

若是找到则返回元素位置,若是找不到则返回-1

    public static int binarySearchLeftmost(int[] arr, int key) {
        int i = 0,j = arr.length-1;
        int candidate = -1; // 记录候选位置
        while (i <= j) {
            int m = (i + j) >>> 1;
            if (key < arr[m]) {
                j = m - 1;
            } else if (arr[m] < key) {
                i = m + 1;
            }else {
                // 记录侯选位置
                candidate = m;
                j = m-1;
            }
        }
        return candidate;
    }

2.找到重复元素中最右侧第一个出现元素的位置

当数组中存在多个待查找的元素时,观察寻找最右侧元素的位置

若是找到则返回元素位置,若是找不到则返回-1

    // 重复元素中找到最右
public static int binarySearchRightmost(int[] arr, int key) {
        int i = 0,j = arr.length-1;
        int candidate = -1;
        while (i <= j) {
            int m = (i + j) >>> 1;
            if (key < arr[m]) {
                j = m - 1;
            }else if (arr[m] < key) {
                i = m + 1;
            }else {
                candidate = m;
                i = m + 1;
            }
        }
        return candidate;
}

3.返回值的优化——返回插入位置

① 最左侧查找优化

当数组中存在多个待查找的元素时,观察寻找最左侧元素的位置

若是找到则返回元素位置,若是找不到则返回插入时的插入位置

    public static int binarySearchLeftmost(int[] arr, int key) {
        int i = 0,j = arr.length-1;
        while (i <= j) {
            int m = (i + j) >>> 1;
            if (key <= arr[m]) {
                // 记录侯选位置
                j = m - 1;
            } else {
                // 记录侯选位置
                i = m + 1;
            }
        }
        // i代表的是 > target目标值的最左侧索引位置
        return i;
    }

② 最右侧查找优化

当数组中存在多个待查找的元素时,观察寻找最右侧元素的位置

若是找到则返回元素位置,若是找不到则返回插入时的插入位置

    // 重复元素中找到最右
    public static int binarySearchRightmost(int[] arr, int key) {
        int i = 0,j = arr.length-1;
        while (i <= j) {
            int m = (i + j) >>> 1;
            if (key < arr[m]) {
                j = m - 1;
            }else {
                i = m + 1;
            }
        }
        // i - 1表示小于等于目标并且最靠近右边的索引位置
        return i - 1;
    }

③ 测试

    public static void main(String[] args) {
        int[] arr = {1,2,4,5,6,7,9};
        System.out.println(binarySearchLeftmost(arr,3));
        System.out.println(binarySearchRightmost(arr,8));
        System.out.println(binarySearchLeftmost(arr,4));
        System.out.println(binarySearchRightmost(arr,5));
    }

三、最左查询和最右查询的应用

二分查找 Leftmost
        Params:a-待查找的升序数组

                        target-待查找的目标值

        Returns:
                        返回 ≥ target 的最靠左索引

二分查找 Rightmost

        Params:a-待查找的升序数组

                        target-待查找的目标值
        Returns:

                        返回 ≤target 的最靠右索引

1.应用1——求前任

        求前任:Leftmost(查找元素) - 1

        求后任:Rightmost(查找元素) + 1

2.应用2——求排名

        数组内已有元素:Leftmost(排名元素) + 1

        数组内不存在元素:Leftmost(后任元素) 

3.应用3——最近邻居

        求出前后任距离,进行比较,取较小值

4.应用4——范围查询

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

折叠cell的学习

折叠cell 文章目录 折叠cell前言示例代码部分实现思路核心内容 前言 笔者在暑假的3GShare的项目中就写了有关折叠cell的内容&#xff0c;这里笔者重新讲一下相关内容。 示例 这里先给出效果图&#xff0c;这里是我们的折叠cell的最后的实现效果&#xff0c;下面来讲解一下相关代…

linux 云主机 pip 安装配置 letsencrypt certbot 为多个域名生成免费 https 证书实录

本文记录了我在华为云 EulerOS linux 云主机使用 python pip 方式安装配置 Let’s Encrypt certbot, 并为我的网站的多个域名生成免费 https 证书的整个过程, 包括 python 环境配置, 下载 certbot 及 certbot-nginx, 一次性生成多个域名的证书及注意事项, 以及最后配置 certbot…

k3s中使用GPU资源

前提是已经安装了nvidia驱动 一、安装nvidia-container-toolkit&#xff08;推荐&#xff09; #复制一份docker配置文件,以防被覆盖 cp /etc/docker/daemon.json /etc/docker/daemon.json.bak #安装NVIDIA Container Toolkitapt-get install nvidia-container-toolkit二、配置…

Python 数据分析笔记— Numpy 基本操作(上)

文章目录 学习内容&#xff1a;一、什么是数组、矩阵二、创建与访问数组三、矩阵基本操作 学习内容&#xff1a; 一、什么是数组、矩阵 数组&#xff08;Array&#xff09;&#xff1a;是有序的元素序列&#xff0c;可以是一维、二维、多维。 array1 [1,2,3] 或[a, b, c, d…

如何通过住宅代理进行高效SSL检查

引言 什么是SSL检查&#xff1f;有哪些内容&#xff1f; 为什么要使用SSL检查&#xff1f; SSL检查是如何进行的&#xff1f; 总结 引言 在现代互联网环境中&#xff0c;SSL/TLS协议已成为确保网络通信安全的基石。随着网络攻击手段的不断演进&#xff0c;仅仅依赖于基础的…

[Leetcode 47][Medium]-全排列 II-回溯(全排列问题)

目录 一、题目描述 二、整体思路 三、代码 一、题目描述 原题地址 二、整体思路 和上一道Leetcode46相比&#xff0c;有变化的地方是要排除重复组合的情况。那么在组合问题中去除重复组合的方法是先对数组进行排序,然后在回溯函数中判断当前元素与上一个元素是否相同,若相同…

Kotaemon:开源的RAG UI

检索增强生成 (RAG) 已成为一种改变游戏规则的方法&#xff0c;可增强大型语言模型的功能。Kotaemon 是由 Cinnamon 开发的开源项目&#xff0c;它站在这项创新的最前沿&#xff0c;提供了一个简洁、可定制且功能丰富的基于 RAG 的用户界面&#xff0c;用于与文档聊天。 Kotae…

【再回顾面向对象】,关键字Satic、final

再回顾面对对象 object&#xff1a;所有类的祖先&#xff0c;所有类的方法 GC&#xff1a;垃圾回收站 一般不会回收对象——Car c new Car(); toString() Hashchde要跟地址对应 尽量不要自己产生跟指针不一样&#xff0c;指针是直接指向地址像是数组的索引找的时候可能会有…

AcWing 902. 最短编辑距离

视频讲解&#xff1a; 【E07 线性DP 编辑距离】 两套代码的字符串存储数组都是从1开始存储的&#xff01;&#xff01;&#xff01;&#xff01; 硬套公式&#xff1a; #include<iostream> #include<algorithm> const int N 1010; using namespace std; int …

文心快码前端工程师观点分享:人机协同新模式的探索之路(一)

&#x1f381;&#x1f449;点击进入文心快码 Baidu Comate 官网&#xff0c;体验智能编码之旅&#xff0c;还有超多福利&#xff01;&#x1f381; 本系列视频来自百度工程效能部的前端研发经理杨经纬&#xff0c;她在由开源中国主办的“AI编程革新研发效能”OSC源创会杭州站1…

mysql基础练习题 1082.销售分析1 (力扣)

1082.编写解决方案&#xff0c;找出总销售额最高的销售者&#xff0c;如果有并列的&#xff0c;就都展示出来。 题目链接&#xff1a; https://leetcode.cn/problems/sales-analysis-i/description/ 建表插入数据&#xff1a; Create table If Not Exists Product (product…

[数据集][目标检测]玉米病害检测数据集VOC+YOLO格式6000张4类别

数据集格式&#xff1a;Pascal VOC格式YOLO格式(不包含分割路径的txt文件&#xff0c;仅仅包含jpg图片以及对应的VOC格式xml文件和yolo格式txt文件) 图片数量(jpg文件个数)&#xff1a;6000 标注数量(xml文件个数)&#xff1a;6000 标注数量(txt文件个数)&#xff1a;6000 标注…

提升学术写作效率:ChatGPT的70个必知技巧!

于其卓越的性能&#xff0c;ChatGPT极大地提升了各行各业的工作效率。正确运用关键词是激发ChatGPT潜能的关键。歪歪学长精心挑选了一系列关键词&#xff0c;通过这些关键词的运用&#xff0c;不仅能简化写作流程&#xff0c;还能提升学术研究成果。共有14个方面&#xff0c;全…

Java 入门指南:Java 并发编程 —— ReentrantLock 实现悲观锁(Pessimistic Locking)

悲观锁 悲观锁&#xff08;Pessimistic Locking&#xff09;是一种悲观的并发控制机制&#xff0c;它基于悲观的假设&#xff0c;即并发冲突会时常发生&#xff0c;因此在访问共享资源&#xff08;如数据库记录或共享变量&#xff09;之前&#xff0c;会先获取独占性的锁&…

内存管理篇-17解开页表的神秘面纱-下

1.页表初探遗留问题-页表的创建过程 使用MMU之前&#xff0c;页表要准备好&#xff0c;怎么准备的&#xff1f;如何把物理内存通过section映射构建页表页表的创建过程分析&#xff1a;__create_page_tables--创建临时页表&#xff0c;然后在开启MMU 页表的大小和用途页表在内存…

您应该使用哪个矢量数据库? 选择最适合您需求的数据库

导言 矢量数据库已成为存储非结构化和结构化数据表示并编制索引的首选。 这些表征被称为向量嵌入&#xff0c;由嵌入模型生成。 向量存储在利用深度学习模型&#xff08;尤其是大型语言模型&#xff09;的应用开发中发挥着至关重要的作用。 什么是矢量数据库&#xff1f; 在…

中国文化艺术孙溟展浅析《绛帖》

孙溟展浅析《绛帖》 《绛帖》是汇集摹刻众多名帖。北宋时潘师旦共摹刻二十卷&#xff0c;以《淳化阁帖》为基础有增加和删减&#xff0c;因为是在降州《今山西新降》摹刻的故此而得名。 《绛帖》 《绛帖》 《绛帖》 《绛帖》 据传潘师旦去世后&#xff0c;他的两个儿子各…

双硬盘双系统怎么装?双硬盘双系统安装教程(win7+win10双系统)

最近有很网友想双硬盘装双系统&#xff0c;考虑到如果哪块硬盘坏了我另一块硬盘还可以启动&#xff0c;以防万一硬盘坏了一块无法使用问题&#xff0c;今天小编给大家带来的双硬盘双系统方法教程。 相关推荐&#xff1a; 如何安装双系统?安装双系统详细步骤 双系统怎么设置启动…

个人旅游网(2.1)——使用阿里云在springboot项目中发送短信

文章目录 一、背景介绍二、详细步骤2.1、申请资质2.2、申请签名2.3、申请模板2.4、申请accessKey秘钥对2.5、SDK的使用[!]2.5.1、项目中导入依赖2.5.2、发短信的工具类 一、背景介绍 验证码发送背后的功能原理图&#xff1a; 想要在项目中实现上述发送验证码的功能&#xff0c…

操作系统面试真题总结(三)

文章收录在网站&#xff1a;http://hardyfish.top/ 文章收录在网站&#xff1a;http://hardyfish.top/ 文章收录在网站&#xff1a;http://hardyfish.top/ 文章收录在网站&#xff1a;http://hardyfish.top/ 什么是进程&#xff1f; 在操作系统中&#xff0c;进程是指正在执…