【算法系列 | 8】深入解析查找算法之—二分查找

news2025/1/19 22:10:23

序言

心若有阳光,你便会看见这个世界有那么多美好值得期待和向往。

决定开一个算法专栏,希望能帮助大家很好的了解算法。主要深入解析每个算法,从概念到示例。

我们一起努力,成为更好的自己!

今天第8讲,讲一下查找算法的二分查找

1 基础介绍

查找算法是很常见的一类问题,主要是将一组数据按照某种规则进行排序。

以下是一些常见的查找算法及其应用场景:

  1. 布隆过滤器(Bloom Filter):适用于判断一个元素是否存在于一个大规模的数据集中,时间复杂度为O(1),但有一定的误判率。
  2. 二分查找(Binary Search):适用于有序数组中查找元素,时间复杂度为O(log n);
  3. 哈希表查找(Hash Table:适用于快速查找和插入元素,时间复杂度为O(1),但需要额外的存储空间;
  4. 线性查找(Linear Search):适用于无序数组中查找元素,时间复杂度为O(n);
  5. 插值查找(Interpolation Search):适用于有序数组中查找元素,时间复杂度为O(log log n),但是对于分布不均匀的数据集效果不佳;
  6. 斐波那契查找(Fibonacci Search):适用于有序数组中查找元素,时间复杂度为O(log n),但需要额外的存储空间;
  7. 树表查找(Tree Search):适用于快速查找和插入元素,时间复杂度为O(log n),但需要额外的存储空间;
  8. B树查找(B-Tree):适用于大规模数据存储和查找,时间复杂度为O(log n),但需要额外的存储空间;

一、二分查找介绍

1.1 原理介绍

二分查找算法(Binary Search)是一种用于在有序数据集合中查找目标元素的高效搜索算法。

它的实现原理基于分而治之(Divide and Conquer)的思想,通过将查找范围逐渐缩小一半来快速定位目标元素。

下面详细讲解二分查找算法的实现原理:

前提条件

  • 数据集合必须是有序的通常是升序排列的。
  • 数据集合应为静态,不应频繁插入或删除元素。

步骤

  1. 初始化指针:首先,确定查找范围,通常是整个数据集合。然后,初始化两个指针:

    • 左指针left)指向查找范围的起始位置,通常是0。
    • 右指针right)指向查找范围的结束位置,通常是数据集合的最后一个元素的索引。
  2. 查找中间元素:计算左右指针的中间位置,即 (left + right) / 2

  3. 比较中间元素:将目标元素与中间位置的元素进行比较。

    • 如果目标元素等于中间位置的元素,则找到了目标元素,查找结束。
    • 如果目标元素小于中间位置的元素,则更新右指针为中间位置的前一个位置,将查找范围缩小为左半部分。
    • 如果目标元素大于中间位置的元素,则更新左指针为中间位置的后一个位置,将查找范围缩小为右半部分。
  4. 重复步骤2和步骤3:不断重复计算中间位置和比较中间元素,直到以下任一条件满足:

    • 找到目标元素,即目标元素等于中间位置的元素。
    • 左指针大于右指针,表示查找范围为空,目标元素不存在。

示例: 假设有一个有序数组 arr,要查找目标元素 target

arr = [1, 3, 5, 7, 9, 11, 13, 15, 17] target = 9

初始时,left 指向0,right 指向8,中间元素为 arr[4],即9。

  1. 目标元素与中间元素相等,查找结束,找到了目标元素。

二分查找算法的关键在于每一次迭代都将查找范围缩小一半,这导致算法的时间复杂度为 O(log n),其中 n 是数据集合的大小。这使得二分查找非常高效,特别适用于大规模的有序数据集合。但需要注意的是,由于它要求数据集合必须是有序的,因此如果数据无序,需要先进行排序操作。

 

1.2 优缺点

优点:

  1. 高效性:二分查找的时间复杂度为 O(log n),其中 n 是数组的长度。由于每次迭代都将搜索范围减半,因此算法的时间复杂度相对较低。在大型有序数组中,二分查找比线性查找要快得多。
  2. 简单易实现:二分查找的实现相对简单,只需按照一定的步骤进行比较和调整指针即可。

缺点:

  1. 仅适用于有序数组:二分查找要求数组必须是有序的,否则无法保证正确的查找结果。如果数组未排序,需要先进行排序操作,这可能会增加额外的时间复杂度。
  2. 内存占用较大:二分查找通常需要占用较大的内存空间,因为它需要存储整个数组。在某些情况下,这可能会成为一个问题,特别是当处理大型数组时。
  3. 难以处理插入和删除操作:二分查找适用于静态数组,即不经常进行插入和删除操作的数组。如果需要频繁地插入或删除元素,由于需要保持数组有序性,可能需要进行额外的操作,导致效率降低。

所以,二分查找算法在查找有序数组中的元素时非常高效。它的主要优点是高效性和简单易实现。

然而,它的缺点是仅适用于有序数组、内存占用较大以及难以处理插入和删除操作。

因此,在选择使用二分查找时,需要根据具体的问题和数据结构的特点综合考虑其优缺点。

1.3 复杂度

这种算法的效率很高,时间复杂度为O(log n),适用于大规模数据集合。

1.4 使用场景

二分查找适用于以下场景:

  1. 有序数组:二分查找要求数组是有序的,因此当我们需要在一个已排序的数组中查找某个元素时,可以使用二分查找来提高查找效率。

  2. 查找静态数据:如果数据集合是静态的,即不会频繁地插入、删除或修改元素,而是在固定的数据集上进行查找操作,那么二分查找是一个很好的选择。

  3. 大型数据集合:二分查找的时间复杂度为 O(log n),其中 n 是数组的长度。相比线性查找的 O(n) 时间复杂度,二分查找在大型数据集合中的查找效率更高。

  4. 查找边界值:由于二分查找可以快速定位有序数组中的中间元素,因此它在查找边界值或者某个特定范围内的元素时非常有用。例如,在一个有序整数数组中查找某个元素第一次出现的位置或最后一次出现的位置。

  5. 数值区间判断:对于满足某种数值规律的数组,可以使用二分查找进行区间判断。例如,对于一个有序的数值范围数组,可以使用二分查找确定某个数值是否在某个区间内。

二、代码实现

2.1 Python实现

代码示例

def binary_search(arr, target):
    left = 0
    right = len(arr) - 1

    while left <= right:
        mid = (left + right) // 2

        if arr[mid] == target:
            return mid
        elif arr[mid] < target:
            left = mid + 1
        else:
            right = mid - 1

    return -1  # 如果未找到目标元素,返回 -1

# 示例使用
arr = [1, 3, 5, 7, 9, 11, 13]
target = 7

result = binary_search(arr, target)

if result != -1:
    print("目标元素在数组中的索引为:", result)
else:
    print("目标元素不在数组中")

代码讲解

在这个示例中,我们定义了一个名为 binary_search 的函数,它接受一个有序数组 arr 和目标元素 target 作为输入参数。算法使用两个指针 left 和 right 来表示搜索的区间。开始时,left 指向数组的起始位置,right 指向数组的末尾位置。

然后,算法进入一个循环,当 left 小于等于 right 时,持续执行以下步骤:计算中间元素的索引 mid,并将其与目标元素进行比较。如果 arr[mid] 等于 target,则找到了目标元素,返回 mid。如果 arr[mid] 小于 target,则说明目标元素可能在 mid 的右侧,将 left 更新为 mid + 1

  1. 如果 arr[mid] 大于 target,则说明目标元素可能在 mid 的左侧,将 right 更新为 mid - 1
  2. 如果循环结束时仍未找到目标元素,说明目标元素不存在于数组中,返回 -1。

运行结果

运行上述代码的结果将会是:

目标元素在数组中的索引为: 3

根据给定的有序数组 [1, 3, 5, 7, 9, 11, 13] 和目标元素 7,经过二分查找算法,找到了目标元素在数组中的索引位置为 3。

2.2 Java实现

代码示例

public class BinarySearch {
    public static int binarySearch(int[] 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
    }

    // 示例使用
    public static void main(String[] args) {
        int[] arr = {1, 3, 5, 7, 9, 11, 13};
        int target = 7;

        int result = binarySearch(arr, target);

        if (result != -1) {
            System.out.println("目标元素在数组中的索引为: " + result);
        } else {
            System.out.println("目标元素不在数组中");
        }
    }
}

代码讲解

在这个示例中,定义了一个名为 BinarySearch 的类,其中包含了一个静态方法 binarySearch。该方法接受一个有序数组 arr 和目标元素 target 作为输入参数,并返回目标元素在数组中的索引。

在 binarySearch 方法中,使用两个指针 left 和 right 来表示搜索的区间。开始时,left 指向数组的起始位置,right 指向数组的末尾位置。

然后,算法进入一个循环,当 left 小于等于 right 时,持续执行以下步骤:

  1. 计算中间元素的索引 mid,并将其与目标元素进行比较。
  2. 如果 arr[mid] 等于 target,则找到了目标元素,返回 mid
  3. 如果 arr[mid] 小于 target,则说明目标元素可能在 mid 的右侧,将 left 更新为 mid + 1
  4. 如果 arr[mid] 大于 target,则说明目标元素可能在 mid 的左侧,将 right 更新为 mid - 1
  5. 如果循环结束时仍未找到目标元素,说明目标元素不存在于数组中,返回 -1。

运行结果

运行上述 Java 代码的结果将会是:

目标元素在数组中的索引为: 3

根据给定的有序数组 [1, 3, 5, 7, 9, 11, 13] 和目标元素 7,经过二分查找算法,找到了目标元素在数组中的索引位置为 3。

三、图书推荐

清华社【秋日阅读企划】领券立享优惠

IT好书 5折叠加10元 无门槛优惠券:活动

活动时间:9月4日-9月17日,先到先得,快快抢

图书名称:

  • 《Python从入门到精通(第3版)(软件开发视频大讲堂)》

图书介绍

《Python从入门到精通(第3版)》从初学者角度出发,通过通俗易懂的语言、丰富多彩的实例,详细介绍了使用Python进行程序开发应该掌握的各方面技术。

全书共分27章,包括初识Python、Python语言基础、运算符与表达式、流程控制语句、列表和元组、字典和集合、字符串、Python中使用正则表达式、函数、面向对象程序设计、模块、文件及目录操作、操作数据库、使用进程和线程、网络编程、异常处理及程序调试、Pygame游戏编程、推箱子游戏、网络爬虫开发、火车票分析助手、数据可视化、京东电商销售数据分析与预测、Web编程、Flask框架、e起去旅行网站、Python自动化办公、AI图像识别工具等内容。

书中所有知识都结合具体实例进行介绍,涉及的程序代码都给出了详细的注释,读者可轻松领会Python程序开发的精髓,快速提升开发技能。 

 

参与方式 

图书数量:本次送出 3 本   !!!⭐️⭐️⭐️
活动时间:截止到 2023-09-16 12:00:00

抽奖方式:

  • 评论区随机抽取小伙伴!

留言内容,以下方式都可以:

  • 根据文章内容进行高质量评论

参与方式:关注博主、点赞、收藏,评论区留言 

中奖名单 

🍓🍓 获奖名单🍓🍓

 中奖名单:请关注博主动态

名单公布时间:2023-09-16 下午

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

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

相关文章

CrossOver 23 正式发布:可在 Mac 上运行部分 DX12 游戏

CodeWeivers 公司于今年 6 月发布了 CrossOver 23 测试版&#xff0c;重点添加了对 DirectX 12 支持&#xff0c;从而在 Mac 上更好地模拟运行 Windows 游戏。 该公司今天发布新闻稿&#xff0c;表示正式发布 CrossOver 23 稳定版&#xff0c;在诸多新增功能中&#xff0c;最值…

【经典小练习】JavaSE—拷贝文件夹

&#x1f38a;专栏【Java小练习】 &#x1f354;喜欢的诗句&#xff1a;天行健&#xff0c;君子以自强不息。 &#x1f386;音乐分享【如愿】 &#x1f384;欢迎并且感谢大家指出小吉的问题&#x1f970; 文章目录 &#x1f384;效果&#x1f33a;代码&#x1f6f8;讲解&#x…

Java学习之--类和对象

&#x1f495;粗缯大布裹生涯&#xff0c;腹有诗书气自华&#x1f495; 作者&#xff1a;Mylvzi 文章主要内容&#xff1a;Java学习之--类和对象 类和对象 类的实例化&#xff1a; 1.什么叫做类的实例化 利用类创建一个具体的对象就叫做类的实例化&#xff01; 当我们创建了…

预算有限但想改善客户服务?教你几招轻松解决~

这里有一个常见的误解&#xff1a;只有大公司需要客户服务。事实是&#xff0c;无论行业规模大小&#xff0c;出色的客户服务对每个企业都至关重要。事实上&#xff0c;企业规模越小&#xff0c;客户服务就越重要&#xff0c;因为他们无法承受失去客户的后果。 不仅如此&#…

连nil切片和空切片一不一样都不清楚?那BAT面试官只好让你回去等通知了。

连nil切片和空切片一不一样都不清楚&#xff1f;那BAT面试官只好让你回去等通知了。 问题 package mainimport ("fmt""reflect""unsafe" )func main() {var s1 []ints2 : make([]int,0)s4 : make([]int,0)fmt.Printf("s1 pointer:%v, s2 p…

【UE虚幻引擎】UE源码版编译、Andorid配置、打包

首先是要下载源码版的UE&#xff0c;我这里下载的是5.2.1 首先要安装Git 在你准备放代码的文件夹下右键点击Git Bash Here 然后可以直接git clone https://github.com/EpicGames/UnrealEngine 不行的话可以直接去官方的Github上下载Zip压缩包后解压 运行里面的Setup.bat&a…

浅谈C++|STL之vector篇

一.vector的基本概念 vector是C标准库中的一种动态数组容器&#xff0c;提供了动态大小的数组功能&#xff0c;能够在运行时根据需要自动扩展和收缩。vector以连续的内存块存储元素&#xff0c;可以快速访问和修改任意位置的元素。 以下是vector的基本概念和特点&#xff1a; 动…

第27章_瑞萨MCU零基础入门系列教程之freeRTOS实验

本教程基于韦东山百问网出的 DShanMCU-RA6M5开发板 进行编写&#xff0c;需要的同学可以在这里获取&#xff1a; https://item.taobao.com/item.htm?id728461040949 配套资料获取&#xff1a;https://renesas-docs.100ask.net 瑞萨MCU零基础入门系列教程汇总&#xff1a; ht…

Anaconda下Jupyter Notebook执行OpenCV中cv2.imshow()报错(错误码为1272)网上解法汇总记录和最终处理方式

零、我设备的相关信息 Python 3.8.8Anaconda3 2021.05查询匹配python3.8.*的OpenCV匹配版本为&#xff1a;4.1.* — 4.2.*&#xff0c;我最后安装4.2.0.32版本如下我记录了 “从发现问题&#xff0c;到不断试错&#xff0c;最后解决问题” 的完整过程&#xff0c;以备自己复盘…

二叉树顺序存储结构

目录 1.二叉树顺序存储结构 2.堆的概念及结构 3.堆的相关接口实现 3.1 堆的插入及向上调整算法 3.1.1 向上调整算法 3.1.2 堆的插入 3.2 堆的删除及向下调整算法 3.2.1 向下调整算法 3.2.2 堆的删除 3.3 其它接口和代码实现 4.建堆或数组调堆的两种方式及复杂度分析…

SpringCloud Eureka搭建会员中心服务提供方-集群

&#x1f600;前言 本篇博文是关于SpringCloud Eureka搭建会员中心服务提供方-集群&#xff0c;希望你能够喜欢 &#x1f3e0;个人主页&#xff1a;晨犀主页 &#x1f9d1;个人简介&#xff1a;大家好&#xff0c;我是晨犀&#xff0c;希望我的文章可以帮助到大家&#xff0c;您…

【Transformer系列】深入浅出理解Attention和Self-Attention机制

一、参考资料 课件&#xff1a;10_Transformer_1.pdf 视频&#xff1a;Transformer模型(1/2): 剥离RNN&#xff0c;保留Attention 二、Attention without RNN Attention模型可以看到全局的信息。 本章节以 Seq2Seq&#xff08; (encoder decoder)&#xff09; 模型为例&…

算法通关18关 | 回溯模板如何解决复原IP问题

18关的前几篇文章看过之后&#xff0c;对回溯的模板问题基本解题思路就知道了&#xff0c;就是固定的for循环问题&#xff0c;外层for循环控制横向&#xff0c;递归控制纵向&#xff0c;还要考虑撤销操作和元素是否能被重复利用问题&#xff0c;重复利用的情景较少&#xff0c;…

【物联网】简要解释RTK(Real-Time Kinematic)>>实时动态差分定位

引言&#xff1a; RTK&#xff08;Real-Time Kinematic&#xff09;技术是一种基于差分GPS的高精度定位技术&#xff0c;它通过实时通信和数据处理&#xff0c;能够提供厘米级甚至亚米级的定位精度。RTK技术在许多领域都得到了广泛应用&#xff0c;如测绘、航空航天、农业等。本…

C++ 内存模型 Memory Model

CPU 现在CPU都是多核结构&#xff0c;每个核心都有自己的一级缓存&#xff0c;二级缓存&#xff0c;以及共享的三级缓存。如下图&#xff0c;其中一级缓存分为指令缓存IL1和数据缓存DL1&#xff0c;二级缓存L2 256kB&#xff0c;三级缓存 L3 8MB。 从上图可以看出L3比L2大得多…

从零开始:PostgreSQL入门完全指南

&#x1f337;&#x1f341; 博主猫头虎&#xff08;&#x1f405;&#x1f43e;&#xff09;带您 Go to New World✨&#x1f341; &#x1f405;&#x1f43e;猫头虎建议程序员必备技术栈一览表&#x1f4d6;&#xff1a; &#x1f6e0;️ 全栈技术 Full Stack: &#x1f4da…

【漏洞复现】大华智慧园区综合管理平台前台任意文件上传漏洞

文章目录 前言声明一、简介二、影响范围三、资产搜索四、漏洞测试四、修复建议前言 大华智慧园区综合管理平台存在前台任意文件上传漏洞,攻击者可通过特定Payload获取服务器敏感信息,进而获取服务器控制权限。 声明 请勿利用文章内的相关技术从事非法测试,由于传播、利用…

树和二叉树的相关概念及结构

目录 1.树的概念及结构 1.1 树的概念 1.2 树的相关概念 1.3 树的表示 1.3.1 孩子兄弟表示法 1.3.2 双亲表示法 1.4 树的实际应用 2.二叉树的概念及结构 2.1 二叉树的概念 2.2 特殊的二叉树 2.3 二叉树的性质 2.4 二叉树的存储 2.4.1 顺序存储 2.4.2 链式存储 1.树…

idea内存不足

The IDE is running low on memory and this might affect performance. Please consider increasing available heap. 参考 【IDEA】The IDE is running low on memory and this might affect performance._datagrip提示ide內存不足_Coder_贾俊浩的博客-CSDN博客 (亲测好用…

零基础教你搭建日用百货线上商城小程序

在当今的数字化时代&#xff0c;小程序商城已成为许多企业和商家的首选平台&#xff0c;尤其是日用百货行业。通过小程序商城&#xff0c;消费者可以更方便地购买各类日用品&#xff0c;商家也可以提高销售效率、扩大市场影响力。本文将详细介绍如何从零开始制作一个日用百货小…