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

序言

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

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

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

今天第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 = 0right = len(arr) - 1while left <= right:mid = (left + right) // 2if arr[mid] == target:return midelif arr[mid] < target:left = mid + 1else:right = mid - 1return -1  # 如果未找到目标元素,返回 -1# 示例使用
arr = [1, 3, 5, 7, 9, 11, 13]
target = 7result = 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.mzph.cn/news/77906.shtml

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

相关文章

UPS电源UL1778认证,不间断电源系统ul1778认证

UPS电源UL1778认证&#xff0c;不间断电源系统ul1778认证 UL认证-不间断电源系统ul1778认证范围&#xff1a; 不间断电源系统&#xff1a;UPS即不间断电源(Uninterruptible Power Supply)&#xff0c;是一种含有储能装置的不间断电源。主要用于给部分对电源稳定性要求较高的设…

C++ std::future

std::future是用来接收一个线程的执行结果的&#xff0c;并且是一次性的。 共享状态shared state future可以关联一个共享状态&#xff0c;共享状态是用来储存要执行结果的。这个结果是async、promise、packaged_task设置的&#xff0c;且这个结果只能设置一次。 创建future …

STM32纯中断方式发送接收数据(串行通信;keil arm5;)

除了main文件其他文件均无修改&#xff0c;正常运行--在keil arm5内

pta java版

7-1 厘米换算英尺英寸 如果已知英制长度的英尺foot和英寸inch的值&#xff0c;那么对应的米是(footinch/12)0.3048。现在&#xff0c;如果用户输入的是厘米数&#xff0c;那么对应英制长度的英尺和英寸是多少呢&#xff1f;别忘了1英尺等于12英寸。 思路&#xff1a; 1英尺12英…

每日一题 2596. 检查骑士巡视方案

难度&#xff1a;中等 很简单&#xff0c;从第 0 步开始模拟即可&#xff0c;唯一sb的就是测试用例中如果&#xff08;0&#xff0c;0&#xff09;处不为0的话就直接false&#xff0c;而不是去找0在哪 我的代码&#xff1a; class Solution:def checkValidGrid(self, grid: L…

Linux中执行bash脚本报错/bin/bash^M: bad interpreter: No such file or directory

文章目录 参考博客&#xff1a; Linux中执行bash脚本报错/bin/bash^M: bad interpreter: No such file or directory 首先在此对这位博主表示感谢。 运行bash脚本会出现两个文件&#xff0c;1037.err和1037.out。 1037.err的文件内容如下&#xff1a; /data/home/user12/.lsbat…

RobotFrameWork自动化测试环境搭建

前言 Robot Framework是一款python编写的功能自动化测试框架。具备良好的可扩展性&#xff0c;支持关键字驱动&#xff0c;可以同时测试多种类型的客户端或者接口&#xff0c;可以进行分布式测试执行。主要用于轮次很多的验收测试和验收测试驱动开发&#xff08;ATDD&#xff0…

Redis-带你深入学习数据类型zset

目录 1、zset有序集合 2、zset相关命令 2.1、添加或更新指定的元素——zadd 2.2、获取有序集合zset的元素个数相关命令&#xff1a;zcard、zcount 2.3、返回指定区间元素相关命令&#xff1a;zrange、arevrange、zrangebyscore 2.4、删除相关命令&#xff1a;zpopmax、zp…

最优化:建模、算法与理论(优化建模——2)

3.10 K-均值聚类 聚类分析是 统计学中的一个基本问题&#xff0c;其在机器学习&#xff0c;数据挖掘&#xff0c;模式识别和图像分析中有着重要应用。聚类不同于分类&#xff0c;在聚类问题中我们仅仅知道数据点本身&#xff0c;而不知道每个数据点具体的标签。聚类分析的任务…

理财是什么?怎样学习理财?

大家好&#xff0c;我是财富智星&#xff0c;今天跟大家分享一下理财是什么&#xff1f;怎样学习理财的方法。 一、理财的基本原则 1、理财应注重投资而不是投机&#xff0c;要与时间为友。 让我们先考虑以下问题&#xff1a;什么样的回报才算是真正的高回报&#xff1f;假设有…

TypeScript命名空间和模块

&#x1f3ac; 岸边的风&#xff1a;个人主页 &#x1f525; 个人专栏 :《 VUE 》 《 javaScript 》 ⛺️ 生活的理想&#xff0c;就是为了理想的生活 ! 目录 命名空间&#xff08;Namespace&#xff09; 命名空间&#xff08;Namespace&#xff09;使用场景 第三方库 兼容…

linux rz乱码文件删除

通过rz上传文件的时候经常会遇到 文件乱码问题&#xff0c;删又删不掉。 使用rz -be的方法上传 遇到乱码文件操作步骤 1. ls -i # 列出文件的编号 2. find . -inum 29229139 -delete # 根据编号删除文件 find 需要扫描的路径 -inum 文件编号 -delete

Vue.js not detected解决方法

扩展程序》管理扩展程序》详情》允许访问文件地址打开

软件测试7大误区

随着软件测试对提高软件质量重要性的不断提高&#xff0c;软件测试也不断受到重视。但是&#xff0c;国内软件测试过程的不规范&#xff0c;重视开发和轻视测试的现象依旧存在。因此&#xff0c;对于软件测试的重要性、测试方法和测试过程等方面都存在很多不恰当的认识&#xf…

Vulnhub系列靶机---HarryPotter-Fawkes-哈利波特系列靶机-3

文章目录 信息收集主机发现端口扫描dirsearch扫描gobuster扫描 漏洞利用缓冲区溢出edb-debugger工具msf-pattern工具 docker容器内提权tcpdump流量分析容器外- sudo漏洞提权 靶机文档&#xff1a;HarryPotter: Fawkes 下载地址&#xff1a;Download (Mirror) 难易程度&#xff…

C++面试/笔试准备,资料汇总

文章目录 后端太卷&#xff0c;建议往嵌入式&#xff0c;qt&#xff0c;测试&#xff0c;音视频&#xff0c;C一些细分领域投简历。有任何疑问评论区聊&#xff0c;我看到了回复 C面试/笔试准备&#xff0c;资料汇总自我介绍项目实习尽可能有1.编程语言&#xff1a;一.熟悉C语言…

【牛客面试必刷TOP101】Day4.BM15删除有序链表中重复的元素-I和BM17二分查找-I

作者简介&#xff1a;大家好&#xff0c;我是未央&#xff1b; 博客首页&#xff1a;未央.303 系列专栏&#xff1a;牛客面试必刷TOP101 每日一句&#xff1a;人的一生&#xff0c;可以有所作为的时机只有一次&#xff0c;那就是现在&#xff01;&#xff01;&#xff01;&…

前端面试题JS篇(6)

ES6 Module 和 CommonJS 模块的区别&#xff1a; CommonJS 是对模块的浅拷⻉&#xff0c;ES6 Module 是对模块的引⽤&#xff0c;即 ES6 Module 只存只读&#xff0c;不能改变其值&#xff0c;也就是指针指向不能变&#xff0c;类似 const&#xff1b; import 的接⼝是 read-o…

ATFX汇市:离岸人民币大幅升值,昨日盘中跌破7.3关口

ATFX汇市&#xff1a;美国CPI数据即将公布之际&#xff0c;周一美元指数大跌&#xff0c;带动离岸人民币升值0.85%&#xff0c;实现3月14日以来的最大单日升值幅度&#xff0c;当日汇率&#xff08;USDCNH&#xff09;最低触及7.292&#xff0c;突破7.3000关口。消息面上&#…

【LangChain系列 8】Prompt模版——少样本prompt模版(二)

原文地址&#xff1a;【LangChain系列 8】Prompt模版——少样本prompt模版(二) 本文速读&#xff1a; 固定少样本prompt模版 动态少样本prompt模版 在上篇文章中介绍了少样本模版的基本用法&#xff0c;本文将介绍 对话模型(chat model) 中 少样本prompt模版的用法。 LangCh…