目录
1.binary_search(arr+n1,arr+n2,value)
2.lower_bound(arr+n1,arr+n2,value)
3.upper_bound(arr+n1,arr+n2,value)
手写lower_bound(), upper_bound()
1.binary_search(arr+n1,arr+n2,value)
2.lower_bound(arr+n1,arr+n2,value)
3.upper_bound(arr+n1,arr+n2,value)
头文件:#include <algorithm>
1.binary_search(arr+n1,arr+n2,value)
int arr[] = {2,3,4,5,6};
int t = binary_search(arr,arr+5,3);
cout << t << endl;
查找区间是[l,r) 左闭右开区间,即arr[0]至arr[4].
查找元素为3, 输出结果为1,
查找成功返回1,查找失败返回0
2.lower_bound(arr+n1,arr+n2,value)
返回值为一个指针 T * p;
p指向 查找>=value下标最小的元素,若找不到,p指向下标为n2的元素
int arr[] = {2,3,3,4,4,5,6};
int* p = lower_bound(arr,arr+7,4);
cout << p-arr << endl; //输出下标为3
p指向第一个4,p-arr的值为3,即第一个4的下标
若要想直接查找下标可以这样写 int pos = lower_bound(arr,arr+7,4)-arr; pos等于3, arr[pos]等于4
若查找一个不存在的元素
int arr[] = {2,3,3,4,4,5,6};
int* p = lower_bound(arr,arr+7,7);
cout << p-arr << endl; //输出下标
p指向arr[7] (不存在),因为数组arr最后一个元素为arr[6]
p-arr为7,这样也可以判断是否查找失败
3.upper_bound(arr+n1,arr+n2,value)
返回值为一个指针 T* p
*p是指向查找比value大且下标最小的元素,若找不到,p指向下标为n2的元素。
注意区别lower_bound()是 >=, upper_bound()只能是大于
int arr[] = {2,3,3,4,4,5,6};
int* p = lower_bound(arr,arr+7,4); p指向的是第一个4
int* p = upper_bound(arr,arr+7,4); p指向的是5
看下面例子:
int arr[] = {2,3,3,4,4,5,6};
int* p = upper_bound(arr,arr+7,3);
cout << p-arr << endl; //输出下标
p-arr 即p指向元素的下标为:3 , 即为第一个4
当使用upper_bound查找一个不存在的元素,同理,p指向arr[7],不存在, p-arr为7
手写lower_bound(), upper_bound()
// 查找>=value下标最小的元素
int myLower_bound(int arr[],int l,int r,int target){
//idx == 数组最后元素下标的后一个指针
//若target比数组里面的值都大,则idx不变
int idx = r+1;
while(l <= r){
int mid= (l+r)>>1;
// trget 在 nums[mid]左边, 此时的mid是符合要求的,但不是最小的
// 二分缩小空间,一定能找到 >= target 且idx是最小的
//相等的值不要考虑,所以相等的值,要向左边缩小
if(target <= arr[mid]){
idx = mid;
r = mid-1;
}
else l = mid+1;
}
return idx;
}
//value大且下标最小的元素
int myUpper_bound(int arr[],int l,int r,int target){
int idx = r+1;
while(l <= r){
int mid = l + (r-l)/2;
//target在arr[mid]的左边,mid符合要求,但不是最小的
//二分查找可以缩小空间,直到mid大于target且最小
if(target < arr[mid]){
r = mid-1;
idx = mid;
}
if(target >= arr[mid]){ //在相等时,要往右边缩小,相等的值不考虑
l = mid+1;
}
}
return idx;
}
总的来说,upper_bound()和lower_bound();
关键的两个因素:
1. idx 在什么条件下,取得? 因为无论是lower_bound()还是upper_bound(), 都是需要找比 target大或者相等的下标,所以 在 target < or <= nums[mid] ,中取得 mid的值,mid的值>= target
2. 在target 与 nums[mid]相等是,l,r该往那边缩小?
lower_bound因为nums中的值和target相同时,也可以,同时相同的值得下标也要求最小,所以向左边缩小
upper_bound不考虑相同的值,所以,相同时往缩小,忽略相同的值
逆向lower_bound()
int main(int argc, char const *argv[]){
int arr[] = {10,9,8,6,3,2,2,2,1,0};
//找比target大或相等(下标最大)的值
int target = 2222;
int l = 0,r = 10-1;
int idx = 0;
while(l <= r){
int mid = (l+r)/2;
if(target < arr[mid]) l = mid+1;
//相等时,取最右边的值,向右边收缩
if(target == arr[mid]){
idx = mid;
l = mid + 1;
}
if(target > arr[mid]) r = mid-1;
}
cout << idx << endl;
}