首页 > 编程语言 >Binary Search 二分查找算法:逻辑的舞蹈,二分法的精准步伐

Binary Search 二分查找算法:逻辑的舞蹈,二分法的精准步伐

时间:2024-09-09 17:22:55浏览次数:12  
标签:Binary Search 二分法 目标值 查找 数组 tempIndex index2 index1

Binary Search 二分查找算法:逻辑的舞蹈,二分法的精准步伐

二分查找算法,也称为二分搜索算法(Binary Search),是一种在有序数组中查找特定元素的高效算法。它通过反复将搜索区间减半来快速定位目标值。二分查找算法的效率远高于线性搜索,因为它每次比较都能排除掉一半的搜索空间。

算法原理:切割问题的艺术,二分法的优雅

二分查找算法的原理基于一个简单的观察:在有序数组中,如果目标值小于当前中间值,则目标值只可能位于中间值的左侧;反之,如果目标值大于当前中间值,则目标值只可能位于中间值的右侧。通过这种方式,每次比较都可以排除掉一半的搜索空间,从而极大地提高查找效率。

  1. 有序性前提:二分查找算法的前提是数组必须是有序的。有序性可以是升序或降序,但在整个查找过程中,数组的顺序必须保持一致。

  2. 初始化指针:算法开始时,设置两个指针,一个指向数组的第一个元素(low),另一个指向数组的最后一个元素(high)。这两个指针定义了当前的搜索范围。

  3. 中间值的计算:在每次迭代中,计算lowhigh之间的中间位置mid,通常使用(low + high) / 2来确定。这个位置的值将用于与目标值进行比较。

  4. 比较与决策

    • 如果arr[mid]等于目标值,那么查找成功,返回mid作为目标值的位置。
    • 如果arr[mid]小于目标值,那么目标值位于mid的右侧,因此将low更新为mid + 1,缩小搜索范围到右侧。
    • 如果arr[mid]大于目标值,那么目标值位于mid的左侧,因此将high更新为mid - 1,缩小搜索范围到左侧。
  5. 迭代过程:重复上述比较和决策过程,直到low大于high,此时表示查找失败,目标值不在数组中。

  6. 终止条件:算法的终止条件是low超过high,这时可以确定目标值不在数组中,或者已经找到目标值。

算法分析

  • 时间复杂度:O(log n)
  • 空间复杂度:O(1)

代码实现详解

二分法的基本思想非常简单,但在具体实现的过程中需要注意边界值问题,以及循环终止条件的判断。下面将以LeetCode题目34. 在排序数组中查找元素的第一个和最后一个位置为例,介绍二分查找算法的一种实现过程。

C 语言实现代码如下:

int* searchRange(int* nums, int numsSize, int target, int* returnSize) {
    // 分配一个大小为2的整数数组,用于存储目标值的起始和结束位置
    int *res = (int*) malloc (sizeof(int) * 2);
    // 初始化结果数组的两个元素为-1,表示未找到目标值
    res[0] = -1; res[1] = -1;
    // 设置返回数组的大小为2
    *returnSize = 2;

    // 定义变量用于存储目标值的起始和结束位置
    int index1, index2;
    // 初始化起始位置为-1,表示数组的左侧界
    index1 = -1;
    // 初始化结束位置为数组的长度,表示数组的右侧界
    index2 = numsSize;

    // 使用二分查找算法查找目标值的起始位置
    while (index1 + 1 != index2) {
        // 计算中间索引
        int tempIndex = (index1 + index2) / 2;
        // 如果中间索引小于0,则跳出循环,因为数组索引从0开始
        if (tempIndex < 0) break;;
        // 如果中间索引处的值大于等于目标值,则将结束位置更新为中间索引
        if (nums[tempIndex] >= target) index2 = tempIndex;
        // 否则,将起始位置更新为中间索引
        else index1 = tempIndex;
    }
    // 如果找到目标值,则更新结果数组的第一个元素为起始位置
    if (index2 < numsSize && nums[index2] == target) res[0] = index2;

    // 重置起始和结束位置,用于查找目标值的结束位置
    index1 = -1, index2 = numsSize;

    // 使用二分查找算法查找目标值的结束位置
    while (index1 + 1 != index2) {
        // 计算中间索引
        int tempIndex = (index1 + index2) / 2;
        // 如果中间索引小于0,则跳出循环
        if (tempIndex < 0) break;
        // 如果中间索引处的值大于目标值,则将结束位置更新为中间索引
        if (nums[tempIndex] > target) index2 = tempIndex;
        // 否则,将起始位置更新为中间索引
        else index1 = tempIndex;
    }
    // 如果找到目标值,则更新结果数组的第二个元素为结束位置
    if (index1 >= 0 && nums[index1] == target) res[1] = index1;

    // 返回结果数组
    return res;
}

Python 实现代码如下:

class Solution:
    def searchRange(self, nums: List[int], target: int) -> List[int]:
        # 初始化结果数组的两个元素为-1,表示未找到目标值
        res = [-1, -1]
        # 设置起始位置为-1,表示数组的左侧界
        index1 = -1
        # 设置结束位置为数组的长度,表示数组的右侧界
        index2 = len(nums)

        # 使用二分查找算法查找目标值的起始位置
        while index1 + 1 != index2:
            # 计算中间索引
            tempIndex = (index1 + index2) // 2
            # 如果中间索引小于0,则跳出循环
            if tempIndex < 0: break
            # 如果中间索引处的值大于等于目标值,则将结束位置更新为中间索引
            if nums[tempIndex] >= target: index2 = tempIndex
            # 否则,将起始位置更新为中间索引
            else: index1 = tempIndex
        # 如果找到目标值,则更新结果数组的第一个元素为起始位置
        if index2 < len(nums) and nums[index2] == target: res[0] = index2

        # 重置起始和结束位置,用于查找目标值的结束位置
        index1, index2 = -1, len(nums)

        # 使用二分查找算法查找目标值的结束位置
        while index1 + 1 != index2:
            # 计算中间索引
            tempIndex = (index1 + index2) // 2
            # 如果中间索引小于0,则跳出循环
            if tempIndex < 0: break
            # 如果中间索引处的值大于目标值,则将结束位置更新为中间索引
            if nums[tempIndex] > target: index2 = tempIndex
            # 否则,将起始位置更新为中间索引
            else: index1 = tempIndex
        # 如果找到目标值,则更新结果数组的第二个元素为结束位置
        if index1 >= 0 and nums[index1] == target: res[1] = index1

        return res

LeetCode相关题目:
34. 在排序数组中查找元素的第一个和最后一个位置
278. 第一个错误的版本
35. 搜索插入位置

标签:Binary,Search,二分法,目标值,查找,数组,tempIndex,index2,index1
From: https://blog.csdn.net/qq_45641147/article/details/142064384

相关文章

  • 【算法笔记】树状数组/Binary Indexed Tree/Fenwick Tree
    前言树状数组,即树形存储的数组,又称BinaryIndexedTree或FenwickTree。抛开它树形的存储结构,这种神奇的数据结构的应用看起来与「树」没什么关系:有一个序列\(A=(A_1,A_2,\dots,A_N)\),在不超过\(\mathcalO(\logN)\)的时间复杂度内完成下列操作:\(\to~\)求\([L,R]\)区间内所......
  • `match()`和`search()`在Python的`re`模块中的区别
    在Python的re模块中,match()和search()是两个非常重要的函数,它们都用于在字符串中搜索正则表达式的匹配项,但它们在搜索的起始位置和返回结果方面存在关键区别。一、match()函数match()函数尝试从字符串的起始位置匹配一个模式,如果不是从起始位置开始匹配的话,match()将不会成功......
  • Elasticsearch-5.6版本安装,添加登录验证,修改密码
    一.ES简介Elasticsearch是一个实时的分布式存储,搜索、分析的引擎。他的模糊查询的强大效率,目前被很多企业所青睐。二.本文背景由于从ElasticStack6.8和7.1版本才开始支持登录验证,所以对于用之前版本的无法升级,又需要添加授权访问或者修改密码,可以参考本文中用到的......
  • Hive 比较BIGINT类型和Binary类型
    鱼弦:公众号:红尘灯塔,CSDN内容合伙人、CSDN新星导师、51CTO(Top红人+专家博主) 、github开源爱好者(go-zero源码二次开发、游戏后端架构https://github.com/Peakchen)HiveBIGINT类型和Binary类型比较HiveBIGINT类型和Binary类型都是用于存储数字数据的类型。它们之间有以下区别:1.......
  • kali——dirsearch的使用
    目录前言下载安装dirsearch目录扫描前言Dirsearch是一个基于Python的Web目录扫描器,用于渗透测试和安全审计中,帮助发现隐藏的资源、备份文件、配置文件等敏感信息。下载安装dirsearchapt-getinstalldirsearch目录扫描靶机centos服务机的www.sqlibs.com网站d......
  • ElasticSearch系列---【批量删除(或修改)索引别名】
    1.问题背景es集群突然查询很慢,定位到是查询近360天指标索引时,查询量太大导致的,每天三四百万流水,频繁查询把数据变成了热点数据,加载到内存中,导致内存不断增大,最终被撑爆,报datatoolarge的错误。2.临时解决方案因为是指标,所以允许为空,后续再重新计算,补上,所以,在生产环境,我们选择......
  • 目录扫描-dirsearch
    dirsearch.py-uhttps://www.xxxx///对xxxx进行目录扫描dirsearch.py-uhttps://www.xxxx/-i200//筛选状态码为200的结果dirsearch.py-uhttps://www.xxxx/-x401,403//排除状态码为401,403的结果dirsearch.py-uhttps://www.xxxx/-i200-oC:\Users\Administrat......
  • Elasticsearch 集群 和 Kibana:最新版 8.15.0 手动安装教程
    1.前言Elasticsearch和Kibana是ElasticStack的核心组件,分别扮演着数据存储与检索、分析和数据可视化的角色。‌1.1Elasticsearch‌简介Elasticsearch‌是一个基于JSON的分布式搜索和分析引擎,它提供了一个分布式、多租户能力的全文搜索引擎,具有HTTP网络接口和无模式......
  • ElasticSearch:基本原理
    文章目录写在前面常见的概念倒排索引TermIndexStoredFieldsDocValuesSegmentLuceneLucene优化高性能高拓展性高可用Node角色分化ElasticSearchElasticSearch写入流程ElasticSearch查询流程最近在项目中用到了ElasticSearch,但只是学了一下怎么用,这里对于ElasticS......
  • 淘宝item_search返回值实践指南
    关键词搜索淘宝商品数据接口是指通过API接口,使用关键词搜索淘宝网上的商品信息,并获取相关数据。这个接口可以通过淘宝开放平台提供的API实现。taobao.item_search公共参数请求地址:名称类型必须描述keyString是调用key(必须以GET方式拼接在URL中)secretString是调用密钥api_nameStri......