二分查找算法及实现

news2025/4/17 23:07:27

概念

二分查找算法也成为折半查找,是一种非常高效的工作于有序数组的查找算法.

实现

需求

现有一个有序数组 arr [1,2,3,4,5,6,7,8,9], 目标值target = 2 ,要求返回目标值target在数组arr中的索引,没有则返回-1;

代码实现

    private int binarySearch(int[] arr, int target) {
        int left=0,right = arr.length-1;
        while (left<=right){
            int mid = (left+right)>>>1;
            if (arr[mid]<target){    // target在arr[mid] 右边
                left=mid+1;
            }else if (target<arr[mid]){   // target在arr[mid] 左边
                right=mid-1;
            }else {           // target和arr[mid]相等
                return mid;   
            }
        }
        return -1;
    }

    public static void main(String[] args) {
        int[] arr = {1,2,3,4,5,6,7,8,9};
        int target = 2;
        Demo1 d = new Demo1();
        int ans = d.binarySearch(arr,target);
        System.out.println(ans);   // 1
    }

需求进阶

现有一个有序数组 arr [1,2,3,3,3,3,3,4,5], 目标值target = 3 ,要求返回目标值target在数组arr中第一次/最后一次出现的索引,没有则返回-1;

代码实现

第一次出现

    private int binarySearchLeft(int[] arr, int target) {
        int left = 0,right = arr.length-1;
        int candidate = -1;       // 标记
        while (left<=right){
            int mid = (left+right)>>>1;
            if (arr[mid]<target){  // target 在arr[mid] 右边
                left=mid+1;
            }else if(target<arr[mid]){ // target 在arr[mid] 左边
                right=mid-1;
            }else {             // target和arr[mid]相等
                candidate = mid;   // 标记出mid
                right=mid-1;       // 继续向左寻找没有则返回candidate
            }
        }
        return candidate;
    }

    public static void main(String[] args) {
        Demo2 d=  new Demo2();
        int[] arr = {1,2,3,3,3,3,3,4,5};
        int target = 3;
        int ans = d.binarySearchLeft(arr,target);
        System.out.println(ans);  // 2
    }

最后一次出现

    private int binarySearchRight(int[] arr, int target) {
        int left = 0,right = arr.length-1;
        int candidate = -1;       // 标记
        while (left<=right){
            int mid = (left+right)>>>1;
            if (arr[mid]<target){  // target 在arr[mid] 右边
                left=mid+1;
            }else if(target<arr[mid]){ // target 在arr[mid] 左边
                right=mid-1;
            }else {             // target和arr[mid]相等
                candidate = mid;   // 标记出mid
                left=mid+1;       // 继续向右寻找没有则返回candidate
            }
        }
        return candidate;
    }

    public static void main(String[] args) {
        Demo3 d=  new Demo3();
        int[] arr = {1,2,3,3,3,3,3,4,5};
        int target = 3;
        int ans = d.binarySearchRight(arr,target);
        System.out.println(ans);  // 6
    }

时间复杂度

O(logn)

刷题实战

力扣704,二分查找icon-default.png?t=N5K3https://leetcode.cn/problems/binary-search/

给定一个 n 个元素有序的(升序)整型数组 nums 和一个目标值 target  ,写一个函数搜索 nums 中的 target,如果目标值存在返回下标,否则返回 -1


示例 1:

输入: nums= [-1,0,3,5,9,12],target= 9输出: 4
解释: 9 出现在nums中并且下标为 4

示例 2:

输入: nums= [-1,0,3,5,9,12],target= 2输出: -1
解释: 2 不存在nums中因此返回 -1
class Solution {
public int search(int[] nums, int target) {
        int left = 0, right = nums.length - 1;
        while (left <= right) {
            int mid = (left + right) >>> 1;
            if (target < nums[mid]) {
                right = mid - 1;
            } else if (target > nums[mid]) {
                left = mid + 1;
            } else {
                return mid;
            }
        }
        return -1;
    }
}

力扣35.搜索插入位置icon-default.png?t=N5K3https://leetcode.cn/problems/search-insert-position/

给定一个排序数组和一个目标值,在数组中找到目标值,并返回其索引。如果目标值不存在于数组中,返回它将会被按顺序插入的位置。

请必须使用时间复杂度为 O(log n) 的算法。

示例 1:

输入: nums = [1,3,5,6], target = 5
输出: 2

示例 2:

输入: nums = [1,3,5,6], target = 2
输出: 1

示例 3:

输入: nums = [1,3,5,6], target = 7
输出: 4
class Solution {
    /**
     * 搜索插入
     * 最左二分搜索
     * @param nums   数组
     * @param target 目标
     * @return int
     */
    public int searchInsert(int[] nums, int target) {
        int left = 0,right = nums.length-1;

        while (left<=right){
            int mid =(left+right)>>>1;
            if (target<=nums[mid]){
                right=mid-1;
            }else{
                left=mid+1;
            }
        }
        return left;
    }
}

力扣 34.在排序数组中查找元素的第一个和最后一个位置icon-default.png?t=N5K3https://leetcode.cn/problems/find-first-and-last-position-of-element-in-sorted-array/

给你一个按照非递减顺序排列的整数数组 nums,和一个目标值 target。请你找出给定目标值在数组中的开始位置和结束位置。

如果数组中不存在目标值 target,返回 [-1, -1]

你必须设计并实现时间复杂度为 O(log n) 的算法解决此问题。

示例 1:

输入:nums = [5,7,7,8,8,10], target = 8
输出:[3,4]

示例 2:

输入:nums = [5,7,7,8,8,10], target = 6
输出:[-1,-1]

示例 3:

输入:nums = [], target = 0
输出:[-1,-1]
class Solution {
    public int[] searchRange(int[] nums, int target) {
        int left = leftmost(nums, target);
        int right = rightmost(nums, target);
        int[] ans = {left,right};
        return ans;
    }

    private int rightmost(int[] a, int target) {
        int i = 0, j = a.length - 1;
        int candidate = -1;
        while (i <= j) {
            int m = (i + j) >>> 1;
            if (target < a[m]) {
                j = m - 1;
            } else if (a[m] < target) {
                i = m + 1;
            } else {
                candidate = m;
                i = m + 1;
            }
        }
        return candidate;
    }

    private int leftmost(int[] a, int target) {
        int i = 0, j = a.length - 1;
        int candidate = -1;
        while (i <= j) {
            int m = (i + j) >>> 1;
            if (target < a[m]) {
                j = m - 1;
            } else if (a[m] < target) {
                i = m + 1;
            } else {
                // 记录候选位置
                candidate = m;
                j = m - 1;
            }
        }
        return candidate;
    }
}

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

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

相关文章

Android加快你的编译速度

工欲善其事&#xff0c;必先利其器。如果每次运行项目都要花费5-10分钟&#xff0c;那人的心态都要崩了。 Gradle构建流程 Gradle 的生命周期可以分为大的三个部分&#xff1a;初始化阶段&#xff08;Initialization Phase)&#xff0c;配置阶段&#xff08;Configuration Pha…

Linux学习之网络管理和配置文件

在CentOS 7中有两种网络配置方法&#xff1a;SysV&#xff08;也称为Sys 5&#xff09;和Systemd。 SysV的命令如下&#xff1a; service network start|stop|restart|status chkconfig --list network Systemd的命令如下&#xff1a; systemctl list-unit-files NetworkManage…

Linux->线程同步

目录 前言&#xff1a; 1 线程同步引入 2 条件变量 2.1 线程饥饿 2.2 条件变量接口 2.3 添加条件变量 3 生产者和消费者模型 前言&#xff1a; 本篇主要讲解了关于线程同步的相关知识&#xff0c;还有生产者和消费者模型的认识和使用。 1 线程同步引入 在讲解线程同步之…

【Unity3D】基于深度和法线纹理的边缘检测方法

1 前言 边缘检测特效中使用屏后处理技术&#xff0c;通过卷积运算计算梯度&#xff0c;检测每个像素周围像素的亮度差异&#xff0c;以识别是否是边缘像素&#xff1b;选中物体描边特效中也使用了屏后处理技术&#xff0c;通过 CommandBuffer 获取目标物体渲染后的模板纹理&…

学习spring: 1.引子

问题 我们来看一段代码: package org.malred;import org.malred.entity.Car; import org.malred.entity.Tire;/*** Hello world!**/ public class App {public static void main(String[] args) {Car car new Car();Tire lt new Tire();car.setLeftTire(lt);Tire rt new T…

状态估计器

文章目录 [toc] 1.状态空间模型1.1.连续状态空间模型1.2.离散状态空间模型 2.矩阵微积分3.二次规划4.概率论4.1.期望与方差4.2.独立事件4.3.向量随机变量4.4.噪声与协方差矩阵4.5.条件概率 5.最小二乘估计5.1.加权最小二乘估计5.2.递推最小二乘估计5.3.状态向量和协方差随时间变…

深入理解WebSocket,让你入门音视频

&#x1f604;作者简介&#xff1a; 小曾同学.com,一个致力于测试开发的博主⛽️&#xff0c;主要职责&#xff1a;测试开发、CI/CD 如果文章知识点有错误的地方&#xff0c;还请大家指正&#xff0c;让我们一起学习&#xff0c;一起进步。&#x1f60a; 座右铭&#xff1a;不想…

Android 使用okhttp监控网络数据

这里使用Okhttp写了一个demo来监听网络请求过程中的一系列数据&#xff0c;包括当前网络类型、请求体、响应体大小&#xff0c;url&#xff0c;请求方式&#xff0c;当然还有本次核心获取域名解析时长&#xff0c;建立连接时长&#xff0c;保持连接时长&#xff0c;请求总时长这…

《C++ Primer》--学习6

IO库 IO类 为了支持使用宽字符的语言&#xff0c;标准库定义了一组类型和对象来操纵 wchar_t 类型的数据。宽字符版本的类型和函数的名字以一个 w 开始。wcin wcout 和 wcerr 是分别对应 cin cout 和 cerr 的宽字符版本对象 IO类型之间的关系 类型 ifstream 和 istringstream…

Vuex 状态管理 —— 核心store

在上一篇当中讲到关于接口请求函数获取数据&#xff0c;拿到 response.data &#xff0c;简化调用&#xff0c;那么在拿到请求的响应数据之后呢&#xff1f;在前面讲到组件间的通信当中&#xff0c;如父子通信(父传子props,子传父$emit)以及组件与组件之前不能通过直接通信&…

【33】用 Docker 部署 Prometheus + Grafana 监控平台

一. Docker部署Prometheus 1.1 下载prom/prometheus镜像 docker pull prom/prometheus 1.2 启动prometheus容器 docker run -itd --nameprometheus -p 9090:9090 prom/prometheus 打开本地http://localhost:9090/ 说明启动成功 1.3 将容器的配置文件复制出来 docker cp pr…

深入理解深度学习——GPT(Generative Pre-Trained Transformer):在不同任务中使用GPT

分类目录&#xff1a;《自然语言处理从入门到应用》总目录 GPT预训练语言模型作为一个标准的语言模型&#xff0c;其输入和输出是固定的&#xff0c;即输入一个词序列&#xff0c;输出该词序列的下一个词。《深入理解深度学习——GPT&#xff08;Generative Pre-Trained Transf…

GAMES101 笔记 Lecture06 Rasterization2(Antialiasing and Z-Buffering)

目录 Antialiasing(反走样)Sampling is Ubiquitous in Computer Graphics(采样在计算机图形学中无处不在)Sampling Artifacts(Errors or Mistakes or Inaccuracies) in Computer Graphics(在计算机图形学中采样的瑕疵)Jaggies(Staircase Pattern)锯齿Moire Pattern in Imaging(…

[进阶]TCP通信实现BS架构,网站开发的原理,线程池优化BS架构

代码演示如下&#xff1a; 服务端 public class Server {public static void main(String[] args) throws Exception{System.out.println("服务端开启&#xff01;");//1.创建ServerSocket的对象&#xff0c;同时为服务端注册端口。ServerSocket serverSocket new…

Wang tile(王浩瓷砖)算法解决贴图平铺重复问题

Wang tile(王浩瓷砖) 大家好&#xff0c;我是阿赵。这次来解决一个贴图重复的问题。 一、问题 做一篇很大面积的草地&#xff0c;一般思路是建立一个地面的面片&#xff0c;然后在材质球里面给他做一个Tiling平铺&#xff0c;增大重复次数。这样整个地面都可以被草地的贴图铺满…

Spring Boot 如何使用 @Validated 注解进行数据校验

Spring Boot 如何使用 Validated 注解进行数据校验 在开发应用程序时&#xff0c;数据校验通常是不可避免的。Spring Boot 提供了许多选项来验证应用程序中的数据&#xff0c;其中一个选项是使用 Validated 注解。本文将介绍如何使用 Validated 注解进行数据校验&#xff0c;并…

操作系统-操作系统结构

✅作者简介&#xff1a;人工智能专业本科在读&#xff0c;喜欢计算机与编程&#xff0c;写博客记录自己的学习历程。 &#x1f34e;个人主页&#xff1a;小嗷犬的个人主页 &#x1f34a;个人网站&#xff1a;小嗷犬的技术小站 &#x1f96d;个人信条&#xff1a;为天地立心&…

【计算机组成原理】Yy-z02硬布线模型机设计

目录 一、Yy-z02模型机的系统结构 二、Yy-z02模型机的数据通路 三、Yy-z02模型机的指令执行 四、Yy-z02模型机的硬布线控制器 一、Yy-z02模型机的系统结构 指令系统的实现 <--- 构造它的硬件系统 硬件系统构造过程&#xff1a; 分析指令格式和各指令的功能确定部件连…

《机器学习公式推导与代码实现》chapter16-集成学习对比与调参

《机器学习公式推导与代码实现》学习笔记&#xff0c;记录一下自己的学习过程&#xff0c;详细的内容请大家购买作者的书籍查阅。 集成学习&#xff1a;对比与调参 虽然现在深度学习大行其道&#xff0c;但以XGBoost、LightGBM、CatBoost为代表的Boosting算法仍有其广泛的用武…

【Applied Algebra】有限状态机和模型检测初探

【Applied Algebra】有限状态机和模型检测初探 摘要:有限状态机(FSM)和模型检测有密切的联系。有限状态机提供了一种用状态转换图来表示系统行为的简单方法。而模型检测是一种针对形式化模型&#xff08;例如有限状态机&#xff09;的验证技术&#xff0c;旨在自动验证模型是否…