Java—二分查找

介绍

二分查找(Binary Search)是一种在有序数组中查找特定元素的搜索算法。其基本思想是将目标值与数组中间的元素进行比较:

  1. 如果目标值等于中间元素,则查找成功。
  2. 如果目标值小于中间元素,则在数组左半部分继续进行二分查找。
  3. 如果目标值大于中间元素,则在数组右半部分继续进行二分查找。

这个过程将不断重复,直到找到目标值或搜索范围为空为止。

实现步骤

下面是二分查找算法的一般步骤:

  1. 初始化两个指针,一个指向数组的起始位置(low),另一个指向数组的结束位置(high)。
  2. 计算中间位置(mid):mid=⌊(low+high)/2⌋mid=⌊(low+high)/2⌋
  3. 比较中间元素与目标值:
    • 如果中间元素等于目标值,返回中间位置。
    • 如果中间元素大于目标值,将high更新为mid - 1。
    • 如果中间元素小于目标值,将low更新为mid + 1。
  4. 重复步骤2和3,直到找到目标值或low大于high为止。

如果最终low大于high,表示目标值不在数组中,可以返回一个表示未找到的值,比如-1。

二分查找的时间复杂度是O(log n),其中n是数组的大小。这使得它在处理大型数据集时非常高效。然而,二分查找要求数组必须是有序的,这是它的一个限制条件。

代码实现

public class BinarySearch {
    
    public static void main(String[] args) {
        // 初始化一个有序数组
        int[] arr = {1, 8, 10, 34, 44, 46, 56, 59, 61, 63, 66, 68, 69, 70, 89, 1000, 1234};
        // 使用递归版本查找目标值89在数组中的索引
        int index = binarySearch(arr, 0, arr.length - 1, 89);
        // 使用循环版本查找目标值89在数组中的索引
        int index1 = binarySearch(arr, 89);
        // 打印两个版本的查找结果
        System.out.println(index + " " + index1);
    }

    // 递归版本的二分查找算法
    private static int binarySearch(int[] arr, int left, int right, int target) {
        // 基本情况:如果left大于right,说明target不在数组中,返回-1
        if(left > right) {
            return -1;
        }

        // 计算中间索引
        int mid = (left + right) / 2;

        // 如果中间元素等于目标值,返回中间索引
        if(arr[mid] == target) {
            return mid;
        } else if(arr[mid] > target) {
            // 如果中间元素大于目标值,在左半部分递归调用二分查找
            return binarySearch(arr, left, mid - 1, target);
        } else {
            // 如果中间元素小于目标值,在右半部分递归调用二分查找
            return binarySearch(arr, mid + 1, right, target);
        }
    }

    // 循环版本的二分查找算法
    private static int binarySearch(int[] arr, int target) {
        // 初始化左右指针
        int left = 0;
        int right = arr.length - 1;

        // 当left小于等于right时,继续循环
        while(left <= right) {
            // 计算中间索引
            int mid = (left + right) / 2;

            // 如果中间元素等于目标值,返回中间索引
            if(arr[mid] == target) {
                return mid;
            } else if(arr[mid] > target) {
                // 如果中间元素大于目标值,更新right为mid-1
                right = mid - 1;
            } else {
                // 如果中间元素小于目标值,更新left为mid+1
                left = mid + 1;
            }
        }
        // 如果没有找到目标值,返回-1
        return -1;
    }
}

测试结果

产生问题

在二分查找算法中,计算中间索引 mid 的表达式 int mid = (left + right) / 2; 可能会在某些情况下导致问题。具体来说,如果 leftright 是非常大的整数,那么它们的和可能会超出 int 类型所能表示的范围,导致整数溢出。

整数溢出会导致 mid 的值不正确,这可能会使二分查找算法无法正确执行,甚至进入无限循环。

举例说明

解决问题

使用位运算: 使用位运算来避免溢出,因为位运算是按位进行的,不会导致溢出。计算 mid 的表达式如下: 

mid=left + (( right − left )  >> 1 )

这里,>> 是右移位运算符,它将 right - left 的二进制表示向右移动一位,相当于除以2。

使用这些方法可以确保在执行二分查找时 mid 的值是正确的,从而避免因整数溢出导致的问题

修改代码

 // 递归版本
    private static int binarySearch(int[] arr, int left, int right, int target) {
        if(left > right) {
            return -1;
        }

        // int mid = (left + right)/2;
        int mid = left + ((right - left) >> 1);

        if(arr[mid] == target) {
            return mid;
        } else if(arr[mid] > target) {
            return binarySearch(arr, left, mid - 1, target);
        } else {
            return binarySearch(arr, mid + 1, right, target);
        }
    }

    // 循环版本
    private static int binarySearch(int[] arr, int target) {
        int left = 0;
        int right = arr.length - 1;

        while(left <= right) {
            //int mid = (left + right)/2;
            int mid = left + ((right - left) >> 1);

            if(arr[mid] == target) {
                return mid;
            } else if(arr[mid] > target) {
                right = mid - 1;
            } else {
                left = mid + 1;
            }
        }
        return -1;
    }

测试结果

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

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

相关文章

汽车悬架分为哪几类

汽车悬架分为哪几类 1)汽车的悬架系统可根据结构分为两种:独立悬架和非独立悬架,独立悬架根据构造又可以分为CDC运动悬架(CDC电磁悬架系统)和空气悬架; 2)当前比较火热的空气悬架,是独立悬架的一种; 3)前轮主要使用麦弗逊式独立悬架 和 双叉臂悬架,后轮主要使用多…

基于 DCT 的图像滤波

需求分析 对于图像去噪这一需求&#xff0c;我们可以通过DCT&#xff08;离散余弦变换&#xff09;算法来实现。DCT是一种基于频域的变换技术&#xff0c;可以将图像从空间域转换为频域&#xff0c;然后通过滤波等处理方式进行去噪。 针对这一需求&#xff0c;我们需要进行以下…

香港优才计划申请时间要多久?各流程申请周期规划,再晚就来不及了!

香港优才计划申请时间要多久&#xff1f;各流程申请周期规划&#xff0c;再晚就来不及了&#xff01; 2024年是香港优才计划不限配额的最后一年&#xff0c;明年政策如何变化还未可知&#xff0c;但如果明年又设置限额了&#xff0c;那么今年最后的机会一定要抓住了。 在这里…

美业SaaS收银系统源码-美团/口碑核销时报错:该商品未在美团/口碑上架怎么办?

美业SaaS系统 连锁多门店美业收银系统源码 多门店管理 / 会员管理 / 预约管理 / 排班管理 / 商品管理 / 活动促销 PC管理后台、手机APP、iPad APP、微信小程序 1. 可能是门店未做映射 • 美团门店映射&#xff1a;需要在【PC运营后端】-【渠道商品】-【美团点评门店管理】&…

elementUI type=“selection“多选框选中 删除 回显 赋值问题 回显数组改变选中状态未改变

业务需求&#xff1a; 点击查询弹列表框 勾选列表选项保存 可删除可重新查询列表添加 遇到的问题&#xff1a;删除之后查询列表selection回显问题 解决&#xff1a;row-click配合:reserve-selection"true"使用 <el-tableref"refPlanTable":data"…

AI时代的服装设计师--AIGC

AI时代的服装设计师--AIGC AIGCAIGC设计能替代真正的设计师吗森马T恤设计AIGC优势、优化 本文记录于去年参加的一次森马T恤设计活动的感受。 AIGC 可以说&#xff0c;近期以来&#xff0c;随着ChatGPT的不断发展&#xff0c;从ChatGPT-3到ChatGPT-4的飞速发展&#xff0c;AIGC…

【Spring Cloud】分布式配置

目录 未来的开发场景为什么需要配置中心配置实时生效配置管理流程 开源配置中心基本介绍DisconfSpring Cloud ConfigApolloNacos Spring Cloud Config介绍配置管理工具体系 案例需求编写 Config Server1.创建配置文件2.创建项目3.添加依赖4.添加注解5.修改配置文件application.…

selenium web 网页测试自动化需要哪些技术?

引言&#xff1a; 在当今互联网时代&#xff0c;网页测试自动化成为了确保软件质量和提高效率的重要手段之一。Selenium是一种功能强大且广泛应用的工具&#xff0c;可用于实现网页测试自动化。本文将带您了解Selenium Web网页测试自动化所需的技术和步骤&#xff0c;以便您从零…

伦敦银和现货白银是一回事吗

伦敦银和现货白银不能直接完全地画上等号&#xff0c;但如果投资者所指指的是国际市场上的现货白银交易&#xff0c;那么二者应该是等同的——因为在国际贵金属投资市场上&#xff0c;现货白银的别称就是伦敦银&#xff0c;伦敦银和现货白银指的其实是同一回事。 因为早在很多个…

MySQL学习——连接服务器和输入查询

MySQL是一个流行的关系型数据库管理系统&#xff08;RDBMS&#xff09;&#xff0c;由瑞典的MySQL AB公司开发&#xff0c;后来被Oracle公司收购。它使用SQL&#xff08;结构化查询语言&#xff09;作为访问和操作数据库的标准语言。 要查看 mysql 客户端程序提供的选项列表&a…

firebase如何自定义上传日志

我们可以很轻松的得到2个代码&#xff1a; Firebase.crashlytics.log(str) Firebase.crashlytics.recordException(ex)这就是firebase提供的自定义日志和excption上传的方法。 但是如果你认为log函数调用后&#xff0c;直接就能查看到日志就错了。 我们在这个page是找不到日志…

Ableton Live 11 Suite for Mac:音乐创作的全能伙伴

在数字音乐创作的广阔天地中&#xff0c;Ableton Live 11 Suite for Mac无疑是一颗璀璨的明星。作为一款专业的音乐制作软件&#xff0c;它集合了音频录制、编辑、混音、母带制作等全方位功能&#xff0c;为Mac用户提供了无与伦比的音乐创作体验。 Ableton Live 11 Suite拥有直…

隆道出席河南ClO社区十周年庆典,助推采购和供应链数字化发展

5月26日&#xff0c;“河南ClO社区十周年庆典”活动在郑州举办&#xff0c;北京隆道网络科技有限公司总裁助理姚锐出席本次活动&#xff0c;并发表主题演讲《数字化采购与供应链&#xff1a;隆道的探索与实践》&#xff0c;分享隆道公司在采购和供应链数字化转型方面的研究成果…

【赠书第25期】C#项目开发实战(微视频版)

文章目录 前言 1 项目构思与需求分析 1.1 项目构思 1.2 需求分析 2 系统设计 2.1 系统架构设计 2.2 数据库设计 2.3 接口设计 3 编码实现 3.1 环境搭建 3.2 编码规范 3.3 编码实现 4 测试与部署 4.1 单元测试 4.2 系统测试 4.3 部署与上线 5 总结与展望 6 推…

图像分割模型LViT-- (Language meets Vision Transformer)

参考&#xff1a;LViT&#xff1a;语言与视觉Transformer在医学图像分割-CSDN博客 背景 标注成本过高而无法获得足够高质量标记数据医学文本注释被纳入以弥补图像数据的质量缺陷半监督学习&#xff1a;引导生成质量提高的伪标签医学图像中不同区域之间的边界往往是模糊的&…

SAP 没有项目类别表存在(表 T184L LF LEIH CHSP)

在项目上&#xff0c;客户在废品出库的时候&#xff0c;出现这个报错 查了相关资料&#xff0c;是因为后台确少配置&#xff1a;IMG-后勤执行-装运-交货-在交货时定义项目类别确定

Strust2 远程代码执行漏洞[s2-005]

漏洞复现环境搭建请参考 http://t.csdnimg.cn/rZ34p kali切换jdk版本请参考 Kali安装JAVA8和切换JDK版本的详细过程_kali安装jdk8-CSDN博客 漏洞原理 Strust2会将http的每个参数名解析成为OGNL语句执行&#xff0c;OGNL表达式通过#来访问Struts的对象&#xff0c;并且通过过…

MySQL实战行转列(或称为PIVOT)实战sales的表记录了不同产品在不同月份的销售情况,进行输出

有一个sales的表&#xff0c;它记录了不同产品在不同月份的销售情况&#xff1a; productJanuaryFebruaryMarchProduct AJanuary10Product AFebruary20Product BJanuary5Product BFebruary15Product CJanuary8Product CFebruary12 客户需求展示为如下的样子&#xff1a; pro…

智能客服:论小红书商家杀出重围的正确姿势!

小红书「起飞」密码 洞悉需求&#xff0c;主动应变 面对众多的互联网平台&#xff0c;选择一个合适的平台宣传自家的品牌&#xff0c;也是一门学问&#xff0c;从“遇事不决&#xff0c;小红书”&#xff0c;这一 slogan 就能精准地捕捉了用户搜索行为的新趋势。 在过去的十…

【机器学习】基于tensorflow实现你的第一个DNN网络

博客导读&#xff1a; 《AI—工程篇》 AI智能体研发之路-工程篇&#xff08;一&#xff09;&#xff1a;Docker助力AI智能体开发提效 AI智能体研发之路-工程篇&#xff08;二&#xff09;&#xff1a;Dify智能体开发平台一键部署 AI智能体研发之路-工程篇&#xff08;三&am…