【转载】本文为CSDN博主「我还年轻我很平凡」的原创文章
原文链接:https://blog.csdn.net/weixin_43784989/article/details/98229031

1、简单二分

那么接下来,我们先来看看二分查找的最常用的场景:查一个有序数组的某一数字是否存在(下标)
图片说明

//target意为目标数字
public int searchNum(int target){
int l = 0;
int r = nums.length - 1;
while (l <= r) {
    int mid = l + ((r - l) >> 1);
    if(nums[mid] == target){
        return mid;
    } else if (target < nums[mid]){
        l = mid + 1;
    } else {
        r = mid - 1;
    }
}
return -1;//表示没有找到该数字
}

2、 复杂二分查找(查找左边界)

假设有一个有序数组{1,2,2,2,3},这个时候让你查找target=2的边界,计算之后返回的结果肯定是是按下标处理过后:(1,3)
这个时候你可能会觉得,这有啥?费这么大劲?用什么二分法?沙13吧?当然,这个数组长度非常短,费不着用什么二分法,一次遍历就可以解决。那么如果数组很长尼?O(N)和O(logN)你倾向与哪个?答案就在下面:配合着图和代码你就知道了:
图片说明

//target=2
public int findLeftBound(int target){
    int l = 0;
    int r = nums.length; //这里需要注意
    while (l < r){
        int mid = l + ((r - l) >> 1);
        if (nums[mid] >= target){  //这里需要注意
            r = mid;
        } else {
            l = mid + 1;
        }
    }
    return l;
}

至于为什么会是这样?这其实就和作用域一样,左闭右开/左闭右闭,自己画个图就明白了

3、复杂二分查找(查找右边界)

其实和查找左边界没什么多大区别,只是在返回的时候需要注意,因为作用域是[L,R),所以在返回有右边界的时候-1再返回:

public int findRightBound(int target){
    int l = 0;
    int r = nums.length;
    while (l < r){
        int mid = l + ((r - l) >> 1);
        if (nums[mid] > target){
            r = mid;
        } else{
            l= mid + 1;
        }
    }
    return r - 1;
}