常用四大二分法查找变形

二分法

二分法用来查找高效,快捷,时间复杂度在O(logN)

二分法查找第一个大于X(大于等于)的数

数组a升序排列

// 在[i+1, n-1]的范围内查找第一个大于x的数的位置
int bingarySearch(int i, long long x){
	if(a[n-1] <= x) return n; //都不大于x,返回n
	int l = i + 1,r = n - 1;
    while (l<r)
    {
        mid = (l+r)/2;
        // 若a[mid]<=x, 说明第一个大于x的数只可能在mid后面
        if(a[mid]<=x){
            l = mid + 1;
        }else{// 若大于,说明在mid之前(包含mid)
            r = mid;
        }
    }
    return l;
}

大于等于

if(a[mid]<x){
            l = mid + 1;
}else{// 若大于,说明在mid之前(包含mid)
          	r = mid;
}

练习:744. 寻找比目标字母大的最小字母

二分法查找最后一个大于X(大于等于)的数

判断最后一个数是不是大于(大于等于)x,如果不是,返回n。

二分法查找最后一个小于等于x(小于)的数

int l=0,r=max;
while (l < r) {
	//取高位,取地位会遇见死循环
    int mid=(l+r+1)/2;
    if(k>=dp[mid])l=mid;
    else r=mid-1;
}

小于

if(k>dp[mid])l=mid;
else r=mid-1;

练习:35. 搜索插入位置

二分法查找第一个小于x(小于等于)的数

判断第一个数是不是小于(小于等于)x,如果是,那就是 a[0],否则不存在。

死循环问题

数据: int[] num = {1,2,3,4,5,6,7,8,9}, 查找小于或者等于8的最小值。

在这里插入图片描述
如上图,此时左坐标是0, 右是8, 那么
mid = (0 + 8) / 2 = 4,num[mid] = num [4] <= k, ,向右找结果,所以有 l = mid,开始下一个循环。
在这里插入图片描述
此时的mid = 6, num[6] = 7;
num[mid] <= k, 向右找 l = 6
下一步:
在这里插入图片描述
可以得到 l = 6, r = 8, mid = (6+8) / 2 = 7,a[7] = 8 <= k,那么有l = mid = 7, r = 8,
推到得到mid = 7, 问题来了上一步的时候mid已经是7了,结果会使得mid一直是7,一直循环下去。
所以如果我们求的是二分法求小于或者等于k的最大值的话,我们mid 必须取得中值的上界。
参考:(图文)二分查找,查指定值、小于或等于k的最大值,大于或等于k的最大值

二分法查找最后一个(第一个等于)x的数

def bsearch_right(nums,target):
    '''求最后一个等于定值的'''
    low = 0
    higt = len(nums) -1
    while low <= higt:
        mid = low + ((higt- low) >>1 )
        if nums[mid] > target:
            high = mid - 1
        elif nums[mid] < target:
            low = mid +1
        else:
            if mid == (len(nums) -1) or nums[mid] != nums[mid+1]:
                return mid
            else:
                low = mid +1 # 将区间往后移
    return  -1

第一个

def bsearch_left(nums,target):
    '''求第一个等于定值 '''
    low = 0
    high = len(nums) - 1
    # 这里需要 <=
    while low <= high:
        # 这里需要注意: 就是使用((high - low) >> 1)需要双扩号
        mid = low + ((high - low) >> 1)
        if nums[mid] < target:
            low = mid + 1
        elif nums[mid] > target:
            high = mid - 1
        else:
            if mid == 0 or nums[mid-1] != target:
                return mid
            else:
                high = mid -1

    return -1

练习:34. 在排序数组中查找元素的第一个和最后一个位置

参考:二分查找算法及其四个变形问题

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值