二分查找

378 阅读1分钟

二分查找:

最传统的二分查找:

初始右边界是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)