二分法应用

二分法模板:

二分法的边界模板分为两种;
一种是左闭右闭的区间写法[left,right]: while(left<=right)

left的改变为left=mid+1,

right的改变为right=mid-1;
一种是左闭右开的区间写法[left,right) : while(left<right)

left的改变为left=mid+1,

right的改变为right=mid;
在二分查找的过程中,保持不变量;这也就是循环不变量。

二分法形式:

以下都是左右闭区间:

第一种形式:找到一个target,找不到就返回-1。

int erfen(int[] nums, int target) {
    int left = 0; 
    int right = nums.length - 1; // 闭区间

    while(left <= right) {    // 闭区间
        int mid = (right + left) / 2;
        if(nums[mid] == target)
            return mid;     //返回target下标
        else if (nums[mid] < target)
            left = mid + 1;   // 注意!!!
        else if (nums[mid] > target)
            right = mid - 1;  // 注意!!!
        }
    return -1;
}

优点:简洁明了,有target直接返回下标,没有target就返回-1.

缺点:不确定target的位置下标。例如:

问题:比如说给你有序数组 nums = [1,2,2,2,3],target = 2,此算法返回的索引是 2,没错。但是如果我想得到 target 的左侧边界,即索引 1,或者我想得到 target 的右侧边界,即索引 3,这样的话此算法是无法处理的。

第二种形式:找到 nums[i] >=  target 的第一个下标

int erfen(vector<int>& nums,int target)
    {
        int left=0,right=nums.size()-1;
        while (left<=right)//闭区间:[left,right]
        {
            int mid=left+(right-left)/2; //确定中间位置
            if (nums[mid]>=target)
            {
                right=mid-1; //target位于: [left,mid-1]
            }
            else
            {
                left=mid+1;  //target位于: [mid+1,right]
            }
        }
        return left;    //结束时,left指向的是目标位置,right指向目标的前一个位置
    }

优点:返回大于等于target的第一个下标。若有多个target,可以确定返回位置。

缺点:没有 找不到target 这种情况的处理。

二分法应用:

解题思路:二分查找 erfen 【时间复杂度O(lgn),n是数组长度】

- 核心要素
- 注意区间开闭,三种都可以
- 循环结束条件:当前区间内没有元素
- 下一次二分查找区间:不能再查找(区间不包含)mid,防止死循环
- 返回值:大于等于target的第一个下标(注意循环不变量)

- 有序数组中二分查找的四种类型(下面的转换仅适用于数组中都是整数)
1. 第一个大于等于x的下标: erfen(x)
2. 第一个大于x的下标:可以转换为`第一个大于等于 x+1 的下标` ,erfen(x+1)
3. 最后一个一个小于x的下标:可以转换为`第一个大于等于 x 的下标` 的`左边位置`, erfen(x) - 1;
4. 最后一个小于等于x的下标:可以转换为`第一个大于等于 x+1 的下标` 的 `左边位置`, erfen(x+1) - 1;

参考:

【二分查找 红蓝染色法】 https://www.bilibili.com/video/BV1AP41137w7/?share_source=copy_web&vd_source=ae7ea0766bb271ec98434838d5057492

  • 10
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值