二分搜索,你真的懂吗?

二分搜索,你真的懂吗?

二分搜索的前提是什么?有序,确实,我们平时从一组数据数据中查找某个数是否存在时,如果这个数组是无序的,那就从头到尾遍历一遍,或者先把数组排序再使用二分查找。其实使用二分不必一定要数组元素有序,只需要数组左边和右边可以区分,例如:

在这里插入图片描述

如图所示,数组的左端点为L,右端点为R。同时数组的红色部分满足一种性质,青色部分满足另外一种性质。

假如此时我要找红色部分的右端点。首先寻找数组的一半mid = (L+R)>>1;如果mid满足某个性质,则L=mid,自然R=mid-1;以上是模板,当发现R=mid-1时,为了避免出现越界的情况,在求mid时要加1,即mid = (L+R)>>1。

假如此时我要找蓝色的左端点。首先寻找数组的一半mid = (L+R)>>1;如果mid满足某个性质,则R=mid,自然L=mid+1;以上是模板。可能这样说有一点生硬,咱们用一个实际的例子来说明。

假如我要从数组[1,1,2,3,3,3,4,5]中确定数字3的首次出现和最后一次出现的位置。先上代码,再来解释。

public static int[] bin(int[] nums,int target){
    int l=0,r=nums.length-1;
    int mid=0;
    while (l<r){
        mid = (l+r)>>1;
        if (nums[mid]>=target){
            r=mid;
        }else {
            l=mid+1;
        }
    }
    if (nums[l]!=target) return new int[]{-1,-1};
        int[] res = new int[2];
        res[0] = l;
        l=0;r=nums.length-1;
        while (l<r){
            mid = l+r+1>>1;
            if (nums[mid]<=target){
                l=mid;
            }else {
                r=mid-1;//这里我们根据实际的应用场景判断出r=mid-1,因此要改变mid=(l+r+1)>>1
            }
        }
        res[1] = l;
    return res;
}

在这里插入图片描述

从上图我们可以看出我们要找的元素就是以目标元素3为界限,当我们需要找3的开始元素时,其实就是找右边元素的左边界;当我们的nums[mid]符合有百年元素的性质时,也就是nums[mid]>=3时,R=mid;否则,当nums[mid]<3时,L=mid+1;最终跳出循环的时候,L=R,此时的nums[L]一定时大于等3的第一个元素,所以判断一下nums[L]是否等于目标元素3,等于则说明数组中存在该元素,否则说明数组中压根不存在该元素。同理,当我们需要找3的结尾元素时,其实就是找左边元素的右边界。

这样解释,你看懂了吗?

同理,当我们需要找3的结尾元素时,其实就是找左边元素的右边界。

这样解释,你看懂了吗?

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值