【算法面试】二分查找:如何在有序数组中高效搜索目标值

目录

题目描述

示例 1:

示例 2:

问题分析

解决方法

方法 1:标准二分查找

方法 2:递归二分查找

方法 3:非递归简化版本

方法 4:带调试信息的版本

详细步骤

总结

博主v:XiaoMing_Java


二分查找是一种常见的算法,广泛应用于计算机科学领域。它的原理是通过不断将目标区间对半划分,从而迅速缩小查找范围。这种方法非常适用于在有序数组中查找特定元素。本篇文章详细解析了如何在有序整型数组中使用二分查找算法来查找目标值,并提供多个代码示例来帮助理解。

题目描述

假设你有一个包含 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

问题分析

二分查找法利用了数组已经排好序(升序)的性质,通过每次将查找范围缩小一半,从而极大地提高了查找效率。算法的核心思想如下:

  1. 选择数组的中间元素作为比较对象。
  2. 如果中间元素正好等于目标值,则直接返回该元素的下标。
  3. 否则,如果目标值小于中间元素,则只需在左半部分继续查找;反之,则在右半部分查找。
  4. 重复上述过程,直到找到目标值或查找范围为空。

解决方法

方法 1:标准二分查找

以下是实现二分查找的一种标准方法:

public int search(int[] nums, int target) {
    int left = 0;
    int right = nums.length - 1;
    
    while (left <= right) {
        int mid = left + (right - left) / 2; // 防止溢出
        int x = nums[mid];
        
        if (x == target) {
            return mid;
        } else if (x > target) {
            right = mid - 1;
        } else {
            left = mid + 1;
        }
    }
    return -1;
}

方法 2:递归二分查找

除了迭代方式,我们还可以采用递归方式实现二分查找:

public int search(int[] nums, int target) {
    return binarySearch(nums, target, 0, nums.length - 1);
}

private int binarySearch(int[] nums, int target, int left, int right) {
    if (left > right) {
        return -1;
    }
    
    int mid = left + (right - left) / 2; // 防止溢出
    int x = nums[mid];
    
    if (x == target) {
        return mid;
    } else if (x > target) {
        return binarySearch(nums, target, left, mid - 1);
    } else {
        return binarySearch(nums, target, mid + 1, right);
    }
}

方法 3:非递归简化版本

有时我们可以进一步简化代码,使其更简洁:

public int search(int[] nums, int target) {
    int left = 0;
    int right = nums.length - 1;
    
    while (left <= right) {
        int mid = (left + right) / 2;
        
        if (nums[mid] == target) {
            return mid;
        }
        
        if (nums[mid] < target) {
            left = mid + 1;
        } else {
            right = mid - 1;
        }
    }
    return -1;
}

方法 4:带调试信息的版本

为了更好地理解算法,可以添加调试信息来跟踪程序执行过程:

public int search(int[] nums, int target) {
    int left = 0;
    int right = nums.length - 1;
    
    while (left <= right) {
        int mid = left + (right - left) / 2;
        System.out.println("Left: " + left + ", Mid: " + mid + ", Right: " + right);

        if (nums[mid] == target) {
            System.out.println("Found target at index: " + mid);
            return mid;
        }
        
        if (nums[mid] < target) {
            left = mid + 1;
        } else {
            right = mid - 1;
        }
    }
    System.out.println("Target not found.");
    return -1;
}

详细步骤

  1. 初始化:设置 left 为数组的起始索引 0right 为数组的末尾索引 n-1
  2. 计算中点:在每个迭代中,计算中点 mid 的索引,避免直接加和可能导致的溢出。
  3. 比较中点值:将中点值与目标值 target 比较:
    • 若相等,返回中点索引。
    • 若中点值大于目标值,将 right 更新为 mid - 1
    • 若中点值小于目标值,将 left 更新为 mid + 1
  4. 重复操作:继续上述步骤直到 left 超过 right,表示目标值不在数组中,返回 -1

总结

二分查找是一种高效的查找算法,其时间复杂度为 O(log n),非常适用于大规模有序数组的查找任务。通过本文展示的多种实现方法,你可以灵活选择适合自己场景的实现方式。此外,理解并掌握二分查找的基本原理和细节,将会对提升你的编码能力和解决问题的效率大有裨益。希望这些方法能够帮助你顺利解决 java.util.concurrent.BrokenBarrierException 问题,确保程序顺利运行。

如果本文对你有帮助 欢迎 关注、点赞、收藏、评论!!!

博主v:XiaoMing_Java

 📫作者简介:嗨,大家好,我是 小 明(小明java问道之路),互联网大厂后端研发专家,2022博客之星TOP3 / 博客专家 / CSDN后端内容合伙人、InfoQ(极客时间)签约作者、阿里云签约博主、全网5万粉丝博主。


🍅 文末获取联系 🍅  👇🏻 精彩专栏推荐订阅收藏 👇🏻

专栏系列(点击解锁)

学习路线(点击解锁)

知识定位

🔥Redis从入门到精通与实战🔥

Redis从入门到精通与实战

围绕原理源码讲解Redis面试知识点与实战

🔥MySQL从入门到精通🔥

MySQL从入门到精通

全面讲解MySQL知识与企业级MySQL实战

🔥计算机底层原理🔥

深入理解计算机系统CSAPP

以深入理解计算机系统为基石,构件计算机体系和计算机思维

Linux内核源码解析

围绕Linux内核讲解计算机底层原理与并发

🔥数据结构与企业题库精讲🔥

数据结构与企业题库精讲

结合工作经验深入浅出,适合各层次,笔试面试算法题精讲

🔥互联网架构分析与实战🔥

企业系统架构分析实践与落地

行业最前沿视角,专注于技术架构升级路线、架构实践

互联网企业防资损实践

互联网金融公司的防资损方法论、代码与实践

🔥Java全栈白宝书🔥

精通Java8与函数式编程

本专栏以实战为基础,逐步深入Java8以及未来的编程模式

深入理解JVM

详细介绍内存区域、字节码、方法底层,类加载和GC等知识

深入理解高并发编程

深入Liunx内核、汇编、C++全方位理解并发编程

Spring源码分析

Spring核心七IOC/AOP等源码分析

MyBatis源码分析

MyBatis核心源码分析

Java核心技术

只讲Java核心技术

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

C语言常用标准头文件

头文件的基础概念 在C的系列语言程序中&#xff0c;头文件&#xff08;通常扩展名为.h&#xff09;被大量使用&#xff0c;它通常包含函数、变量、结构体等的声明和定义&#xff0c;以及一些宏定义和类型定义。头文件的主要作用是为了方便管理和重用代码&#xff0c;它可以被多…

【电源专题】案例:电量计遇到JEITA充电芯片,在高温下无法报百怎么办?

在使用电量计芯片时,我们期望的是在产品工作温度下、在产品最低和正常充电电流下都要能报百。 所谓报百,就是电量计RSOC(电量百分比)能到达100%。这看起来简单,如果是常规的操作的话,那么电压达到充电截止要求、电流达到充电截止要求、容量累积变化满足要求,RSOC=100%肯…

[分布式网络通讯框架]----ZooKeeper下载以及Linux环境下安装与单机模式部署(附带每一步截图)

首先进入apache官网 点击中间的see all Projects->Project List菜单项进入页面 找到zookeeper&#xff0c;进入 在Zookeeper主页的顶部点击菜单Project->Releases&#xff0c;进入Zookeeper发布版本信息页面&#xff0c;如下图&#xff1a; 找到需要下载的版本 …

外部网络如何访问内网?

在现代信息化时代&#xff0c;随着企业规模的扩大和业务范围的扩展&#xff0c;越来越多的企业需要实现外部网络访问内网的需求。外部网络访问内网指的是在外部网络环境下&#xff0c;通过互联网等公共网络途径&#xff0c;实现对企业内部网络的访问和操作。这种需求的出现&…

iptables动作总结

ACCEPT动作 将数据包放行&#xff0c;进行完此处理动作后&#xff0c;将不再比对当前链的其它规则&#xff0c;直接跳往下一个规则链。 范例如下&#xff1a; #新增自定义链TEST_ACCEPTiptables -t filter -N TEST_ACCEPT#新增自定义链TEST_ACCEPT2iptables -t filter -N TES…

仿迪恩城市门户分类信息网discuz模板

Discuz x3.3模板 仿迪恩城市门户分类信息网 (GBK) Discuz模板 仿迪恩城市门户分类信息网(GBK)

Spring 内部类获取不到@Value配置值问题排查(附Spring代理方式)

目录 一、实例问题 1、现象 2、原因 3、解决 二、Spring的代理模式 1、静态代理&#xff08;Static Proxy&#xff09; 1&#xff09;原理 2&#xff09;优缺点 3&#xff09;代码实现 2、JDK动态代理&#xff08;JDK Dynamic Proxy&#xff09; 1&#xff09;原理 …

用于射频功率应用的氮化铝电阻元件

EAK推出了新的厚膜氮化铝 &#xff08;AlN&#xff09; 电阻器和端接系列&#xff0c;以补充公司现有的产品。传统上&#xff0c;射频功率电阻元件采用氧化铍&#xff08;BeO&#xff09;陶瓷材料作为陶瓷基板;然而&#xff0c;由于国际上要求从产品中去除BeO的压力&#xff0c…

第T2周:彩色图片分类

&#x1f368; 本文为&#x1f517;365天深度学习训练营 中的学习记录博客&#x1f356; 原作者&#xff1a;K同学啊 &#x1f449; 要求&#xff1a; 学习如何编写一个完整的深度学习程序了解分类彩色图片会灰度图片有什么区别测试集accuracy到达72% &#x1f9be;我的环境&am…

【ajax核心05】宏任务与微任务

ES6之后引入Promise对象(用来管理异步任务)&#xff0c;让JS引擎也可以发起异步任务 一&#xff1a;异步任务分类 异步任务分为&#xff1a;宏任务与微任务 宏任务 由浏览器环境执行的异步代码 具体宏任务分类 微任务 由JS引擎执行的代码 创建Promise对象时&#xff0c;…

数据清洗!即插即用!异常值、缺失值、离群值处理、残差分析和孤立森林异常检测,确保数据清洗的全面性和准确性,MATLAB程序!

适用平台&#xff1a;Matlab2021版及以上 数据清洗是数据处理和分析中的一个关键步骤&#xff0c;特别是对于像风电场这样的大型、复杂数据集。清洗数据的目的是为了确保数据的准确性、一致性和完整性&#xff0c;从而提高数据分析的质量和可信度&#xff0c;是深度学习训练和…

STM32单片机系统

1.STM32最小系统 微型计算机&#xff08;面&#xff09; 单片机最小系统是指能够将单片机芯片运行所必需的最少的硬件电路集成在一起的系统。 它是一种基本的单片机应用系统&#xff0c;通常由主芯片&#xff0c;时钟电路&#xff0c;复位电路&#xff0c;电源电路&#xff0c…

407串口01发送

实验一&#xff1a; 工程。 链接&#xff1a;https://pan.baidu.com/s/1g8DV4yZWOix0BbcZ08LYDQ?pwd2176 提取码&#xff1a;2176串口1的使用。发送功能。 单片机发送信息到电脑。 通过串口进行通信。 首先单片机这边。 单片机这边&#xff0c;需要对单片机的串口模块进行使…

小车启动底盘功能包

传感器与小车底盘的集成 新建功能包 catkin_create_pkg mycar_start roscpp rospy std_msgs ros_arduino_python usb_cam ydlidar_ros_driver功能包下创建launch文件夹&#xff0c;launch文件夹中新建launch文件&#xff0c;文件名start.launch。 内容如下 <!-- 机器人启动…

雷达标定与解析

融合雷达与解析雷达数据的相关代码。感谢开源社区的贡献。以下代码继承了很多人的工作。 如果是单雷达&#xff1a; 直接进行标定&#xff0c;所以就是接收相关的话题然后发布。 lidar_calibration_params.yaml&#xff1a; calibration:在这个接口里面x_offset: 0.0y_offset:…

免费内网穿透工具 ,快解析内网穿透解决方案

在IPv4公网IP严重不足的环境下&#xff0c;内网穿透技术越来越多的被人们所使用&#xff0c;使用内网穿透技术的好处有很多。 1&#xff1a;无需公网ip 物以稀为贵&#xff0c;由于可用的公网IP地址越来越少&#xff0c;价格也是水涨船高&#xff0c;一个固定公网IP一年的成本…

想让Python序列切片更高效?这些技巧你不可不知!

目录 1、自定义类实现切片 🍏 1.1 实现__getitem__方法 1.2 支持正负索引与步长 2、利用 collections.abc 模块 🧠 2.1 继承MutableSequence类 2.2 重写关键方法 3、使用标准库itertools.slice 🍲 3.1 itertools工具介绍 3.2 slice函数应用实例 4、通过生成器实…

Docker Compose--安装Nginx--方法/实例

原文网址&#xff1a;Docker Compose--安装Nginx--方法/实例_IT利刃出鞘的博客-CSDN博客 简介 说明 本文介绍Docker Compose如何安装Nginx。 目录结构 ├── config │ ├── cert │ │ ├── xxx_bundle.pem │ │ └── xxx.key │ ├── conf.d │ …

APP客户端接口本地缓存,降低请求量和请求峰值,减少云资源成本

背景 静态信息&#xff1a;非实时有状态的数据 针对资源位、评价等静态信息在xx点高峰时进行缓存&#xff0c;达到降低请求量和请求峰值的目标。 在成本预算控制下&#xff0c;云资源成本和WAF都受限于请求峰值。 出于业务和数据安全考虑&#xff0c;公司希望接入阿里云的WAF&a…

头歌——机器、深度学习——手写体识别

第1关&#xff1a;神经网络基本概念 任务描述 本关任务&#xff1a;根据本节课所学知识完成本关所设置的选择题。 相关知识 为了完成本关任务&#xff0c;你需要掌握&#xff1a;1.神经网络基本概念。 神经网络基本概念 神经网络由输入层、隐藏层、输出层组成&#xff1b;…