二分查找边界问题分析

本文详细分析了二分查找算法在寻找有序序列中目标值的边界情况,包括左边界和右边界的问题。通过讨论不同场景,阐述了如何处理边界条件以确保正确找到目标值的边界,并给出了相应的代码实现。
摘要由CSDN通过智能技术生成

二分查找边界问题分析

概述

二分查找对于有序序列性能非常优越,能够达到O(logn)级别,因此熟练使用二分搜索是非常重要的。但是,正如Knuth评价的那样:
  Although the basic idea of binary search is comparatively straightforward, the details can be surprisingly tricky…
  意思是说,尽管二分搜索算法的基本思想比较简单,但是细节却非常棘手。我觉得这样的评价真的是非常客观而且到位的,如果不花点心思研究一下二分搜索算法的边界问题,还真的很难做到熟练使用二分搜索算法。这里,我就把自己学习时候的理解和体会作以总结和分析。

二分查找的基本思路

最基本的二分查找算法的实现如下代码所示:对一个有序序列而言(我们此处只讨论非递减序列)对于某个要查找的值,我们每次取搜索区间的中间位置,根据中间位置来决定下一步该如何做,则可以分为以下三种情况:
  1.如果中间位置的值是我们要查找的值,则返回对应的下标
  2.如果中间位置的值比我们要查找的值小,则可以推出我们要查找的值在搜索区间的后半部分,更新搜索区间即可(因为序列非递减)
  3.如果中间位置的值比我们要查找的值大,则可以推出我们要查找的值在搜索区间的前半部分,更新搜索区间即可
  4.重复上述步骤,直到找到查找值,或者区间长度小于0(即搜索区间不存在)则未找到。

//a[]为要搜索的数组,n表示数组的长度,x表示要搜索的值
int BinarySearch(int a[],int n,int x){
   
    int left=0,right=n-1;               //初始化区间长度
    while(left<=right){
                    //当区间长度大于0时,进行循环,假如循环一直走到尽头,则循环结束时,显然有left=right+1
        int mid=left+(right-left)/2;    //取中间位置,这里的写法可以避免left+right溢出的情况发生
        if(a[mid]==x)                   //如果找到查找值,返回下标
            return mid;
        else if(a[mid]>x)               //如果中间位置的值大于目标值,则向前半部分查找,此时收缩右边界,因为mid位置已经判定过,故right=mid-1
            right=mid-1;
        else if(a[mid]<x)               //如果中间位置的值小于目标值,则向后半部分查找,此使收缩左边界,因为mid位置已经判定过,故left=mid+1
            left=mid+1;
    }                                   //如果查找失败,则必有left之前的所有值都<x,即left所在的位置为x需要插入的位置
    return left;      
}

注意:我这里特别强调了left最后所在位置的特征,这对于理解边界情况非常有帮助,请仔细理解left下标之前的所有值都小于x

二分查找的边界情况

如果非递减序列中,查找的目标值有多个,则有时候我们需要找到这个重复值的左边界和重复值的右边界(如果此值存在的情况下),如下图所示:
  

二分查找的左边界

在理解算法的写法之前,我们先来简单分析和理解一下左边界的特征和规律,不难发现左边

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值