二分查找的模板的应用 acwing789. 数的范围

二分法的本质是不断划分区域,通过与要找的值比较大小,确定比这个值大的区域和小于等于这个值的区域,或是比这个值小的区域和大于等于这个值的区域。
这就取决于你是从左边找还是从右边找了
二分查找使用于有序数组

int bsearch_1(int l,int r){
    while(l<r){
        int mid=l+r>>1;
        if(check(mid))r=mid;
        else l=mid+1;
    }return l;
    
}
int bsearch_2(int l,int r){
    while(l<r){
        int mid=l+r+1>>1;
        if(check(mid))l=mid;
        else r=mid-1;
    }return l;
    
}//如何记忆,存在mid-1的情况mid的初始值要取得大一些。

while括号里等号是用来确定最后要找的数的位置的。
acwing 789 数的范围

在这里插入图片描述

//折半查找肯定适用于有序数组
#include<iostream>
using namespace std;
const int N=100002;
int q[N];
//二分的两个模板
//整数二分
//二分的本质不一定是单调性
//二分的本质是边界

int main(){
    int n,m;
    cin>>n>>m;
    for(int i=0;i<n;i++)
    cin>>q[i];
    //遇到输入一个执行一次,并输出结果的如何处理
    //用while 循环
    while(m--){
    int x;
    cin>>x;//输入要查找的数
    int l=0,r=n-1;
     while(l<r){
        int mid=l+r>>1;
        if(q[mid]>=x)r=mid;
        else l=mid+1;
     }
    if(q[l]!=x){cout<<"-1 -1"<<endl; }
    else {
        cout<<l<<" ";
        //再用二分查找找出最后一个等于x的值
        //只需要接着上一个元素的基础上找就行
        int r=n-1;//应该选择从左往右找更合适啊,能找到最后一个与这个相等的
        while(l<r){
            int mid=l+r+1>>1;
            if(q[mid]<=x)l=mid;
            else r=mid-1;
            
        }
        cout<<l<<endl; 
    }
    }
    return 0;
}

这两种模板的选择就是取决于你要找的数左边是都小于等于target,还是你要找的数右边都是大于target,
看你是从哪边开始想这个问题的,比如这个升序数组里有两个target,那么你一开始按照,这个target的右边的元素都比这个元素>=,那么你就能最终找到第一个target的位置,然后第二个就是从第一个target的位置开始往右找,所以你就得从此时的位置往右,那么你要找的target肯定比你左边的元素都大,此时用从左边找的模板nums[mid]<=target
如果你想都用从右边找,那么你寻找第二次的元素的l得+1,不能接着从已经找到的target 的位置再找了,否则还是找的第一个target。
但这个第二部分,只能从左往右找!!!

二分查找的应用

68. 0到n-1中缺失的数字
在这里插入图片描述中心思想就是缺失的位置会由后面比他大的数来补上,那么也就是说,倘若当前的元素未缺失,那就说明左边的都未缺失,应该去右边寻找缺失的部分,l=mid+1;
否则就是当前这个位置r=mid
而且这个也不用考虑模板选择,就是找不着了得去右边找即l=mid+1;

chatgpt说的
如果 nums[mid] 不等于 mid,说明缺失的数字在 mid 的左边,更新 r 为 mid。
否则,说明缺失的数字在 mid 的右边,更新 l 为 mid+1

这个题要考虑一个边界问题:
当n=1时,整个数组就是空的,此时用容器的判空操作
当缺少的是最后一个元素时,则存在缺失现象
就会让r指向最后一个元素,若仍匹配,那就让r+1

class Solution {
public:
    int getMissingNumber(vector<int>& nums) {
        
        //如果当前位置缺失则会让后面的补上这个位置。所以缺失的位置应该是在未缺失的位置的后面
        //如果未出现缺失现象那么就是,最后一个元素缺失,此时应让r++
        //还要考虑数组里没有数字,即n=1的时候,范围是0-0
        if(nums.empty())return 0;
        int l=0,r=nums.size()-1;
        while(l<r){
            int mid= l+r>>1;
            if(nums[mid]!=mid)r=mid;
            else l=mid+1;
        }if(nums[r]==r)r=r+1;
        return r;
        
    }
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值