【查找算法】之二分查找

news2024/9/22 17:31:57

一、算法介绍

二分查找,也称为折半查找,是一种在有序数组中查找特定元素的高效算法。对于包含 n 个元素的有序数组,二分查找的步骤如下:

  • 确定搜索范围:首先,将要查找的元素与数组中间的元素进行比较。如果查找的元素等于中间元素,则找到了目标值。否则,如果目标值小于中间元素,则在左半边继续查找;如果目标值大于中间元素,则在右半边继续查找。
  • 缩小搜索范围:根据比较结果,将搜索范围缩小为剩余数组的一半,并重复执行步骤 1,直到找到目标值或确定目标值不存在。

二分查找算法的关键优势在于每一步都能将搜索范围减半这使得算法的时间复杂度为 O(log n),相比线性搜索算法的 O(n) 更加高效,尤其是对于大型数据集。

二、时间复杂度计算

二分搜索最坏的情况就是折半一直找到最后一个元素,首先观察规律

开始时,是从n个元素中查找

第一次折半时,是从 n 2 \frac{n}{2} 2n个元素中查找

第二次折半时,是从 n 4 \frac{n}{4} 4n个元素中查找

假设第k次折半后只剩一个元素,即是从 n 2 k \frac{n}{2^k} 2kn个元素中查找

n 2 k \frac{n}{2^k} 2kn= 1,即 n = 2 k 2^k 2k,由对数定义知道 k = log ⁡ 2 n \log_{2}n log2n,在计算机科学中如果没有特殊说明,默认就是以2为底,即k= log ⁡ n \log n logn

即操作k次才能找到最后一个元素,所以时间复杂度为O( log ⁡ n \log n logn)

三、Java代码示例

package com.datastructures;

/**
 * 二分查找算法
 * @author hulei
 */
public class BinarySearchExample {
    /**
     * 在有序的整型数组中使用二分查找算法来寻找指定目标值的索引。
     * @param arr 一个已排序的整型数组。
     * @param target 要在数组中查找的目标值。
     * @return 如果目标值存在于数组中,则返回其索引;如果目标值不存在,则返回-1。
     */
    public static int binarySearch(Integer[] arr, int target) {
        int left = 0; // 初始化左边界为数组的第一个元素的索引
        int right = arr.length - 1; // 初始化右边界为数组的最后一个元素的索引

        while (left <= right) { // 当左边界不大于右边界时继续循环
            int mid = left + (right - left) / 2; // 计算中间位置,避免溢出
            if (arr[mid] == target) {
                return mid; // 如果中间位置的元素等于目标值,返回其索引
            } else if (arr[mid] < target) {
                left = mid + 1; // 如果中间位置的元素小于目标值,调整左边界
            } else {
                right = mid - 1; // 如果中间位置的元素大于目标值,调整右边界
            }
        }

        return -1; // 如果没有找到目标值,返回-1
    }

    /**
     * 递归实现的二分查找。
     *
     * @param arr 有序整型数组,查找范围在此数组内。
     * @param target 目标值,我们要在数组中找到这个值的索引。
     * @param left 查找范围的左边界。
     * @param right 查找范围的右边界。
     * @return 如果找到目标值,返回其索引;如果未找到,返回-1。
     */
    public static int binarySearchRecursive(Integer[] arr, int target, int left, int right) {
        // 当左边界大于右边界时,说明已经搜索完毕但未找到目标值,返回-1
        if (left > right) {
            return -1;
        }
        // 计算中间位置,避免直接计算(left + right) / 2可能的溢出问题
        int mid = left + (right - left) / 2;

        // 如果中间位置的元素等于目标值,返回其索引
        if (arr[mid] == target) {
            return mid;
            // 如果中间位置的元素小于目标值,说明目标值可能在中间位置的右边,递归搜索右半部分
        } else if (arr[mid] < target) {
            return binarySearchRecursive(arr, target, mid + 1, right);
            // 如果中间位置的元素大于目标值,说明目标值可能在中间位置的左边,递归搜索左半部分
        } else {
            return binarySearchRecursive(arr, target, left, mid - 1);
        }
    }

    public static void main(String[] args) {
        Integer[] sortedArray = {11, 22, 33, 44, 55, 66, 77, 88, 99, 100, 111, 123};
        int targetValue = 111;
        System.out.println("while循环实现二分查找");
        int resultWithoutRecursive = binarySearch(sortedArray, targetValue);
        if (resultWithoutRecursive != -1) {
            System.out.println("元素位置索引为: " + resultWithoutRecursive);
        } else {
            System.out.println("没有发现目标元素");
        }
        System.out.println("================================================");
        System.out.println("递归实现二分查找");
        int resultRecursive = binarySearchRecursive(sortedArray, targetValue, 0, sortedArray.length - 1);
        if (resultRecursive != -1) {
            System.out.println("元素位置索引为: " + resultRecursive);
        } else {
            System.out.println("没有发现目标元素");
        }

    }
}

代码分析:
该Java函数包含在一个名为BinarySearchExample的类中,提供了两种实现二分查找算法的方法:binarySearchbinarySearchRecursive。二分查找算法用于在有序数组中查找指定目标值的索引。

1. binarySearch方法:

  • 参数:一个已排序的整型数组arr和要查找的目标值target。
  • 返回值:如果目标值存在于数组中,则返回其索引;如果目标值不存在,则返回-1。
  • 实现方式:使用循环迭代来缩小查找范围,直到找到目标值或确定目标值不存在。初始化左边界left为数组的第一个元素的索引,右边界right为数组的最后一个元素的索引。在每次循环中,计算中间位置mid,并将mid与目标值比较,根据比较结果调整左右边界的值。

2. binarySearchRecursive方法:

  • 参数:一个已排序的整型数组arr,要查找的目标值target,以及查找范围的左边界left和右边界right。
  • 返回值:如果目标值存在于数组中,则返回其索引;如果目标值不存在,则返回-1。
  • 实现方式:使用递归来实现二分查找。通过不断缩小查找范围来查找目标值。计算中间位置mid,并将mid与目标值比较,根据比较结果递归调用函数自身,传入更新后的左右边界。
    在main方法中,示例代码演示了如何使用这两种方法在有序数组中查找目标值,并输出查找结果。

比如我要在以下数组 Integer[] sortedArray = {11, 22, 33, 44, 55, 66, 77, 88, 99, 100, 111, 123}
中查找目标值为55的元素的索引位置,返回结果为4,即元素55的索引位置为4
在这里插入图片描述

四、两种方式实现二分查找的算法优劣

二分查找的循环实现递归实现都有其各自的优缺点,具体如下:

循环实现

1. 循环实现的优点:

  • 空间效率:循环实现通常不需要额外的堆栈空间,因为控制流是通过迭代进行的,不会导致函数调用栈的增长。
  • 可读性:对于一些开发者来说,循环可能更容易理解和实现,逻辑更直观。
  • 性能:在处理大量数据时,由于避免了递归调用的开销,循环实现可能更快。
    2. 循环实现的缺点:
  • 代码结构:虽然更直观,但代码可能稍微复杂一些,需要手动管理边界条件。

递归实现

1. 递归实现的优点:

  • 简洁性:递归实现的代码通常更简洁,逻辑更优雅,尤其是对于熟悉递归思维的开发者。
  • 表达力:递归直接反映了二分查找的分治思想,易于理解算法的本质。

2. 递归实现的缺点:

  • 空间效率:递归会增加栈的使用,当递归深度很大时,可能导致栈溢出。
  • 效率:由于存在函数调用开销,递归在某些情况下可能比循环慢。
  • 可读性:对不熟悉递归的人来说,递归代码可能更难理解。

在实际应用中,选择哪种实现方式通常取决于具体场景,如数据规模、性能要求、代码可读性和维护性等因素。对于小规模数据或对代码简洁性有较高要求的情况,递归可能是不错的选择。而对于大规模数据或对性能敏感的场合,循环实现可能更为合适。

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

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

相关文章

基于 Linux 自建怀旧游戏之 - 80 款 H5 精品小游戏合集

1&#xff09;简介 最近又找到了一款宝藏游戏资源分享给大家&#xff0c;包含 80 款 H5 精品小游戏&#xff0c;都是非常有趣味耐玩的游戏&#xff0c;比如 植物大战僵尸、捕鱼达人、贪吃蛇、俄罗斯方块、斗地主、坦克大战、双人五子棋、中国象棋 等等超级好玩的 H5 小游戏&…

Chrome浏览器命令行妙用:使你的网上冲浪更加无障碍

引言 在当今数字化时代&#xff0c;网络浏览器已成为我们日常生活中不可或缺的工具之一。对于许多人来说&#xff0c;Google Chrome浏览器是首选&#xff0c;不仅因为它的普及度&#xff0c;更因为它提供的丰富功能和高度的可定制性。在Chrome的众多特性中&#xff0c;命令行功…

景源畅信数字:抖音怎么挂橱窗商品?

抖音作为一款短视频分享平台&#xff0c;近年来逐渐融入了电商功能&#xff0c;其中“橱窗”就是商家或个人展示和销售商品的一个重要工具。如何在抖音上挂橱窗商品&#xff0c;成为了众多商家关注的焦点。 一、确保账号资质&#xff1a;在抖音上挂橱窗商品前&#xff0c;需要确…

iOS ------ JSONModel源码

一&#xff0c;JSONModel的基本使用 1&#xff0c;基本使用方法 - (instancetype)initWithDictionary:(NSDictionary *)dict error:(NSError **)err; - (instancetype)initWithData:(NSData *)data error:(NSError **)error; - (instancetype)initWithString:(NSString *)str…

yolov5-pytorch-Ultralytics训练+预测+报错处理记录

一、前言 玩一段时间大模型&#xff0c;也该回归一下图像识别。本项目用于记录使用基于Ultralytics的yolov5进行目标检测测试。为什么用Ultralytics呢&#xff1f;答案有3 1、其良好的生态&#xff0c;方便我们部署到其它语言和设备上。因此本次测试结论&#xff1a;大坑没有&…

华为手机连接电脑后电脑无反应、检测不到设备的解决方法

本文介绍华为手机与任意品牌电脑连接时&#xff0c;出现连接后电脑无反应、检测不到手机连接情况的解决方法。 最近&#xff0c;因为手机的存储空间愈发紧缺&#xff0c;所以希望在非华为电脑中&#xff0c;将华为手机内的照片、视频等大文件备份、整理一下。因此&#xff0c;需…

2024年化学材料、清洁能源与生物技术国际学术会议(ICCMCEB2024)

2024年化学材料、清洁能源与生物技术国际学术会议(ICCMCEB2024) 会议简介 2024国际化学材料、清洁能源和生物技术大会&#xff08;ICCMCEB2024&#xff09;将在长沙隆重举行。本次会议旨在汇聚来自世界各地的化学材料、清洁能源和生物技术领域的专家学者&#xff0c;共同探…

Vite构造Vue3

环境安装 node.js安装-CSDN博客 初始化Vue项目安装脚手架_vue init webpack安装脚手架-CSDN博客 选择Vue框架 &#xff0c;项目名称可以自定义&#xff0c;我使用默认的 vite-project 选择JS 进入项目安装依赖 安装路由

创新指南|组织健康仍然是企业创新长期绩效的关键

麦肯锡关于组织健康的最新调查结果表明&#xff0c;它仍然是当今全球市场中价值创造的最佳预测者和竞争优势的可持续来源。在本文中&#xff0c;我们将探讨最新的 OHI 结果&#xff0c;并重点介绍该指数揭示的有关领导力、数据和技术以及人才管理的一些更引人注目的见解。我们还…

【华为】IPSec VPN手动配置

【华为】IPSec VPN手动配置 拓扑配置ISP - 2AR1NAT - Easy IPIPSec VPN AR3NATIPsec VPN PC检验 配置文档AR1AR2 拓扑 配置 配置步骤 1、配置IP地址&#xff0c;ISP 路由器用 Lo0 模拟互联网 2、漳州和福州两个出口路由器配置默认路由指向ISP路由器 3、进行 IPsec VPN配置&…

数据结构===树

文章目录 概要概念相关概念 有哪些常用的树小结 概要 树是一种新的数据结构&#xff0c;不同于数组&#xff0c;链表。就像大自然中的树&#xff0c;看下这个数据结构&#xff0c;很有意思&#xff0c;有一个主干&#xff0c;然后还有很多树叉&#xff0c;即支干。不错&#xf…

SpringMVC响应数据

三、SpringMVC响应数据 3.1 handler方法分析 理解handler方法的作用和组成&#xff1a; /*** TODO: 一个controller的方法是控制层的一个处理器,我们称为handler* TODO: handler需要使用RequestMapping/GetMapping系列,声明路径,在HandlerMapping中注册,供DS查找!* TODO: ha…

Autodesk AutoCAD 2025 for Mac:强大的二维三维绘图工具

Autodesk AutoCAD 2025 for Mac是一款专为Mac用户打造的计算机辅助设计软件&#xff0c;它在继承了AutoCAD系列软件的优秀传统的基础上&#xff0c;针对Mac系统进行了全面优化&#xff0c;为用户提供了更出色的绘图和设计体验。 这款软件不仅支持用户创建和编辑复杂的二维几何图…

python 中如何匹配字符串

python 中如何匹配字符串&#xff1f; 1. re.match 尝试从字符串的起始位置匹配一个模式&#xff0c;如果不是起始位置匹配成功的话&#xff0c;match()就返回none。 import re line"this hdr-biz 123 model server 456" patternr"123" matchObj re.matc…

打破地域界限:海外短剧小程序引领全球影视潮流

海外短剧小程序在打破地域界限、引领全球影视潮流的创作内容方面&#xff0c;展现了巨大的潜力和价值。这些小程序通过提供跨文化的影视内容&#xff0c;促进了全球观众之间的文化交流与理解&#xff0c;同时也为全球影视创作者提供了一个展示才华的平台。 首先&#xff0c;海外…

Swift 周报 第五十期

文章目录 前言新闻和社区WWDC24&#xff1a;6 月 10 日至 14 日 (太平洋时间)苹果“内忧外患”&#xff0c;库克中国求援苹果被起诉&#xff01;市值一夜蒸发8000亿元 提案通过的提案正在审查的提案拒绝的提案 Swift论坛推荐博文话题讨论关于我们 前言 本期是 Swift 编辑组自主…

某东抢购某台脚本-低调

某东抢购某台脚本 小白操作-学习使用 注意&#xff1a; 本文部分变量已做脱敏处理&#xff0c;仅用于测试和学习研究&#xff0c;禁止用于商业用途&#xff0c;不能保证其合法性&#xff0c;准确性&#xff0c;完整性和有效性&#xff0c;请根据情况自行判断。技术层面需要提…

React 第二十一章 Portals

Portals 被翻译成传送门&#xff0c;是 React 库中的一个特性&#xff0c;它允许开发者将子组件渲染到父组件 DOM 层次结构之外的其他地方。 React 组件通常是在其父组件的 DOM 层次结构中渲染的&#xff0c;这意味着它们的输出会被插入到父组件的某个 DOM 元素中。然而&#…

图像处理-图像平滑

图像平滑 前言一、概念介绍1.1 图像的平滑1.2 图像中噪声的分类1.3 MATLAB的添加噪音代码 二、空间域平滑滤波2.1 均值滤波2.2 原理计算 总结 前言 在图像的获取、传输和存储过程常常收到各种噪声的干扰和影响&#xff0c;使得图像的质量下降&#xff0c;为了获得高质量的数字…

云仓酒庄携手央视共筑品牌新高度,酒类行业广告战略迈向新征程

随着酒类市场的日益繁荣与竞争的加剧&#xff0c;品牌宣传与推广在酒类行业中的地位愈发凸显。近日&#xff0c;云仓酒庄宣布与中视中州&#xff08;央视代理机构&#xff09;达成2024-2025年度央视广告战略合作&#xff0c;云仓酒庄副总裁周玄代表云仓酒庄签约&#xff0c;这一…