0
点赞
收藏
分享

微信扫一扫

AcWing算法基础课-二分

知年_7740 2022-01-31 阅读 73

二分

二分本质是用来查找满足某种性质的边界点
在给定区间内,能找到某种性质(check函数):

二分可以用来寻找这个性质的边界:满足某种性质的第一个元素;或者是满足某种性质的最后一个元素。
从而有两个不同模板

注意二分法一定能找到满足某种性质的边界点,但它不一定是你要找的目标,目标一不定在区间内,先写check函数,根据check函数更新区间,再判断用哪个模板。

二分模板一共有两个,分别适用于不同情况。
算法思路:
假设目标在闭区间[l,r]中,每次将区间长度缩小一半,当l=r时,我们就找到了目标值。
版本1

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;
}

版本2

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;
}

AcWing 789.数的范围

在这里插入图片描述

#include<iostream>
using namespace std;
const int N=1e5+10;
int q[N];
int n,m;

int main()
{
    cin>>n>>m;
    for(int i=0;i<n;i++)
        cin>>q[i];
    while(m--)
    {
        int k;
        cin>>k;
        int l=0,r=n-1;
        while(l<r)
        {
            int mid=(l+r)>>1;
            if(q[mid]>=k)
                r=mid;
            else
                l=mid+1;
        }
        if(q[l]!=k)
            cout<<-1<<' '<<-1<<endl;
        else
        {
            cout<<l<<' ';
            int l=0,r=n-1;
            while(l<r)
            {
                int mid=(l+r+1)>>1;
                if(q[mid]<=k)
                    l=mid;
                else
                    r=mid-1;
            }
            cout<<l<<' '<<endl;
        }
        
    }
    return 0;
}

AcWing 790.数的三次方根

在这里插入图片描述

#include<iostream>
using namespace std;
int main()
{
    double x;
    cin>>x;
    double l=-100,r=100;//根据题目范围 开三次方根 估计答案大概范围
    while(r-l>1e-8)
    {
        double mid=(l+r)/2;
        if(mid*mid*mid>=x)
            r=mid;
        else
            l=mid;
    }
    printf("%.6lf\n",l);
    return 0;
}

浮点数的平方根

#include<iostream>
using namespace std;
int main()
{
    double x;
    cin>>x;
    double l=0,r;
    //一个浮点数开平方,答案绝对值一定大于等于0,但是右边界根据输入浮点数是否大于1确定
    if(x>1)
        r=x;
    else
        r=1;
    while(r-l>1e-8)//经验: 保留6位小数 1e-8 4位 1e-6 多2
    {
        double mid=(l+r)/2;
        if(mid*mid>=x) r=mid;
        else l=mid;
    }
    printf("%.6lf\n",l);
    return 0;
}
举报

相关推荐

0 条评论