二分搜索的写法

Posted cryingrain

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了二分搜索的写法相关的知识,希望对你有一定的参考价值。

二分搜索框架

int L,R,key;
while(L<=R)
{
    int mid=(L+R)>>1;
    if(a[mid]<key or a[mid]<=key)
        L=mid+1;
    else
        R=mid-1;
}
return L or R;

问题

二分搜索大家都很熟悉。如果待查区间内只有一个key值,要求找出key,那么一切都很容易。

但是如果有多个key,或者没有key,在不依赖现有库函数的情况下,怎么做到返回第一个key的位置,或最后一个key的位置,或者第一个大于key的位置此类的要求呢?

解决

其实很简单,只需要关注两个部分,一个是比较,另一个是返回值。

比较的控制

  1. 假设区间内有key,那么a[mid]<=key的写法会使得左端点一直向右移动。这样当L==R时,找到的就是最后一个key的位置。

    同理,a[mid]<key的写法会使得右端点向左移动,当L==R时,找到的就是第一个key的位置。

  2. 若区间内没有key,那么两种写法是等价的,因为不存在a[mid]==key的情况。

返回值的问题

​ 注意到,二分搜索结束的条件是L>R,那么最后的状态一定是LR的右边,二者相邻。

  1. 如果有key,那么根据上文中所述的写法的不同,会有两种情况。

    1.1 R指向最后一个keyLR右侧。

    1.2 L指向第一个keyRL左侧。

  2. 如果没有key。那么只有一种情况,即L指向第一个大于key的元素,R指向最后一个小于key的元素。

至此问题就解决了,只需要控制这两部分,就可以实现任意一种二分搜索的变体。

示例

  1. 查找第一个大于key的元素位置(类似stl的upper_bound的功能)

    int L,R,key;
    while(L<=R)
    {
        int mid=(L+R)>>1;
        if(a[mid]<=key)
            L=mid+1;
        else
            R=mid-1;
    }
    return L;
    
  2. 查找第一个key的位置,若不存在,则返回第一个大于key的元素位置(类似stl的lower_bound的功能)

    int L,R,key;
    while(L<=R)
    {
        int mid=(L+R)>>1;
        if(a[mid]<key)
            L=mid+1;
        else
            R=mid-1;
    }
    return L;
    
  3. 查找最后一个小于等于key的元素的位置

    int L,R,key;
    while(L<=R)
    {
        int mid=(L+R)>>1;
        if(a[mid]<=key)
            L=mid+1;
        else
            R=mid-1;
    }
    return R;
    

以上是关于二分搜索的写法的主要内容,如果未能解决你的问题,请参考以下文章

LeetCode Binary Search Summary 二分搜索法小结

力扣35:搜索插入位置, 总结了二分查找的通用模板写法, 彻底解决几个易混淆问题

数组: 总结了二分查找的通用模板写法, 彻底解决几个易混淆问题, 力扣35:搜索插入位置

Java 求解搜索插入位置

二分查找法

LeetCode代码模板,刷题必会