头文件:<algorithm>
功能:扩展版二分查找(upper_bound查找第一个大于给定数的元素地址,lower_bound查找第一个大于等于给定数的元素地址)
条件:数组必须有序
返回值:返回目标的地址,可以减去查找起始地址得到下标,查找失败返回查找范围长度,查找成功返回下标
基础使用
int nums[n];
//返回nums中第一个大于等于aim的元素地址,若不存在则返回nums[n+1]地址
第一个参数查找左边界地址(包括)
第二个参数查找右边界地址(不包括)
第三个参数aim查找元素
int *num = lower_bound(nums,nums+n,aim);
//返回nums中第一个大于等于aim的元素下标
int pos = lower_bound(nums,nums+n,aim) - nums;
upper_bound用法也是这样,只不过是返回大于aim的元素地址
int *num = upper_bound(nums,nums+n,aim);
int pos = upper_bound(nums,nums+n,aim);
vector容器也可以使用该方法
vector<int>nums;
int pos = upper_bound(nums.begin(),nums.end(),aim) - nums.begin();
注意点
1.使用lower_bound和upper_bound前必须保证数组有序,可以先使用sort排序。
2.在一般数组中(定义数组以及vector中)这两个函数的时间复杂度均为log(n),但是在set等关联式容器中直接使用这两个函数的时间复杂度为O(n^2),只有使用set等关联式容器中封装的upper_bound和lower_bound时间复杂度才可以达到O(log(n))。
set<int>s;
s.lower_bound(3);//在集合s中查找第一个大于等于3的元素。注意 这里就不是元素地址了
进阶使用
1.查找第一个小于等于指定元素的元素下标
int nums[n];
//使用sort降序
sort(num,num+n,greater<int>()); //这里的greater<int>()含义指的是上一个元素比下一个元素大
//lower_bound 查找小于等于aim的元素下标
int pos = lower_bound(num,num+n,aim,greater<int>()) - num;
2.查找第一个小于指定元素的元素下标
int nums[n];
//使用sort降序
sort(num,num+n,greater<int>()); //这里的greater<int>()含义指的是上一个元素比下一个元素大
//upper_bound 查找小于等于aim的元素下标
int pos = upper_bound(num,num+n,aim,greater<int>()) - num;
3.自定义查找规则
struct Point
{
int x, y;
Point(int x,int y)
{
this->x = x;
this->y = y;
}
};
//比较函数
bool cmp(Point a, Point b)
{
if(a.x != b.x) //按第一个元素降序排序,若第一个元素相等再按照第二个元素降序排列
return a.x > b.x;
return a.y > b.y;
}
Point a[4] = {Point(0,1),Point(1,3),Point(1,2),Point(2,3)};
sort(a,a+4,cmp);
for(int i = 0; i < 4; i++)
{
cout<<a[i].x<<" "<<a[i].y<<endl;
}
cout<<endl;
int pos = upper_bound(a,a+4,Point(2,2),cmp) - a;
cout<<a[pos].x<<" "<<a[pos].y<<endl;
/*
2 3
1 3
1 2
0 1
1 3
*/