【STL】 lower_bound和upper_bound

发布时间 2023-12-23 09:17:59作者: 綾川雪絵

在STL提供的 algorithm 头文件中,提供了两个函数:upper_bound 和 lower_bound ,这俩函数功能 ”类似“,但并不相同。

  1. lower_bound(begin,end,val)在有序的数组连续地址的[begin,end)内找到第一个位置并返回其地址,使得val插入这个位置前面,数组仍然保持有序
  2. upper_bound(begin,end,val)在有序的数组连续地址的[begin,end)内找到最后个位置并返回其地址,使得val插入这个位置前面,数组仍然保持有序

即:lower_bound函数可以返回某数第一次出现的位置,upper_bound可以返回某数最后一次出现的位置(的后面)

因为返回的是地址,那么减去arr.begin()即可得到下标。

其原理都是二分,时间复杂度O(NlogN)

实验代码如下:

int test[6] = {1,2,3,3,6,8};

cout << lower_bound(test,test+6,3) - test << endl;
cout << upper_bound(test,test+6,3) - test << endl;

输出为2 4

 

如果查找数组元素不存在与数组中呢,那么根据二分查找的原理,有三种结果

  1. 如果查找元素tar小于有序数组的第一个元素,那么返回数组第一个下标
  2. 如果查找元素tar大于有序数组的最后一个元素,那么返回数组最后一个下标
  3. 如果查找元素不存在但也不满足1,2,那么返回数组内第一个大于tar的数组元素下标

实验代码如下:

int test[6] = {1,2,3,3,6,8};

cout << lower_bound(test,test+6,4) - test << endl;
cout << upper_bound(test,test+6,4) - test << endl;

输出为:4 4(6的下标)

 

在从大到小的排序数组中,重载lower_bound()和upper_bound()

lower_bound( begin,end,num,greater<type>() ):从数组的begin位置到end-1位置二分查找第一个小于或等于num的数字,找到返回该数字的地址,不存在则返回end。通过返回的地址减去起始地址begin,得到找到数字在数组中的下标。

upper_bound( begin,end,num,greater<type>() ):从数组的begin位置到end-1位置二分查找第一个小于num的数字,找到返回该数字的地址,不存在则返回end。通过返回的地址减去起始地址begin,得到找到数字在数组中的下标。

 

用二分查找实现lower_bound和upper_bound的函数实现如下

int lowerBound (int arr[],int l,int r,int tar) {
    while (l<r) {
    int mid = (l + r) >> 1;
    if (test[mid] < tar) l=mid+1;
    else r=mid;
    }
    return l;
}
int upperBound (int arr[],int l,int r,int tar) {
    while (l<r) {
    int mid = (l + r) >> 1;
    if (test[mid] <= tar) l=mid+1;
    else r=mid;
    }
    return l;
}