二分查找:
最传统的二分查找:
初始右边界是n-1;
循环跳出条件:right>=left 用left>right作为不存在target的判定条件。
//在严格递增序列中查找数target,若不存在则返回-1
int binarySearch(int[] num, int target){
int left=0;
int right=num.length-1;
int mid;
while(right>=left){
mid=left+(right-left)/2; //注意避免左右下标相加超过int范围
if(num[mid]==target) return mid;
else if(num[mid]>target){
right=mid-1;
}
else{
left=mid+1;
}
}
return -1; //查找失败返回-1
}
需要注意到的点:
lower_bound和upper_bound函数都在解决一个“寻找有序序列中第一个满足某条件的元素的位置”的问题。
循环跳出条件:right>left 这样right和left可以夹出一个确定的下标。
注意这两个函数的初始右边界都是n(序列长度)而不是n-1,这是因为要考虑target比序列中所有的元素都要大的情况(此时应该返回n,即假设它存在,那它应该存在的位置)。
//在非严格递增序列中查找第一个大于或等于target的下标
//若不存在则返回“如果它存在,那它应该在的位置”
int lower_bound(int[] num, int target){
int left=0;
int right=num.length;
int mid;
while(right>left){
mid=left+(right-left)/2;
if(num[mid]>=target){
r=mid;
}
else{
l=mid+1;
}
}
return left;
}
//在非严格递增序列中查找第一个大于target的下标
//若不存在则返回“如果它存在,那它应该在的位置”
int upper_bound(){
int left=0;
int right=num.length;
int mid;
while(right>left){
mid=left+(right-left)/2;
if(num[mid]>target){
r=mid;
}
else{
l=mid+1;
}
}
return left;
}
以上两个二分查找综合起来就可以找到一个左开右闭的区间[L, R)