二分

基本思路

建议排列之后再使用,每次找取中间值,若中间值大于我想要的,直接把右边的丢掉;若中间值小于我想要的,那就把左边的丢掉。

具体步骤

1.建议排列之后再使用,设置一个l,一个r分别为左右边界;
2.若mid = (l + r) / 2,用于寻找数组中第一个满足条件的数字,则check(mid),即所求条件与mid的大小关系,若mid大,则让r = mid,丢掉右边的所有数字;若mid小,则让l = mid + 1,不然当数组只剩下两个时会无限循环,丢掉左边的数字;
3.若mid = (l + r + 1 ) / 2,则用于寻找数组中最后一个满足条件的数字,则check(mid)即所求条件与mid的大小关系,若mid大,则让r = mid - 1,不然当数组只剩下两个时会无限循环,丢掉右边的所有数字;若mid小,则让l = mid,丢掉左边的数字;

代码模板

寻找数组中第一个满足条件的数字

int l = 0 , r = n - 1;
while(l < r)
{
      int mid = (l + r) >> 1;
      if(check(mid))
            {
                r = mid;
            }
      else
            {
                l = mid + 1;
            }
}

寻找数组中最后一个满足条件的数字

int l = 0 , r = n - 1;
while(l < r)
{
      int mid = (l + r + 1) >> 1;
      if(check(mid))
            {
                l = mid;
            }
      else
            {
                r = mid - 1;
            }
}

例题

题目链接https://www.acwing.com/problem/content/791/

题解

#include<bits/stdc++.h>
using namespace std;
int n , q;
int arr[100005];
int main()
{
    cin >> n >> q;
    for(int i = 0 ; i < n ; i++)
    {
        cin >> arr[i];
    }
    while(q--)
    {
        int x;
        cin >> x;
        int l = 0 ;
        int r = n - 1;
        while(l < r)//直到l = r时停下,返回一个下标
        {
            int mid = l + r >> 1;//找最低位直接相加除以二
            if(arr[mid] >= x)//最低位先动r
            {
                r = mid;
            }
            else
            {
                l = mid + 1;//l要多加一位
            }
        }
        if(arr[l] != x)
        {
            cout << "-1 -1" << endl;
        }
        else
        {
            cout << l << ' ';//l等于r,任意一个都行
            l = 0 , r = n - 1;//再来一次
            while(l < r)
            {
                int mid = (l + r + 1) >> 1;//找最高位要多加一个1,防止tle
                if(arr[mid] <= x)
                {
                    l = mid;//最高位从左边开始缩减
                }
                else
                {
                    r = mid - 1;
                }
            }
            cout << l << endl;
        }
    }


    return 0;
}

浮点数二分

思路
思想一样,不过浮点数中值非常严格,因此几乎不用再取,比较简单;

例题

链接https://www.acwing.com/problem/content/792/
给定一个浮点数 n,求它的三次方根

题解

#include<bits/stdc++.h>
using namespace std;
double n , l , r , mid;
double c_3(double x)
{
    return x*x*x;
}
int main()
{
    cin >> n;
    l = -10000 , r = 10000;
    while(r - l >= 1e-7)
    {
        mid = (l + r) / 2;
        if(c_3(mid) >= n)
        {
            r = mid;
        }
        else
        {
            l = mid;
        }
    }
    cout << fixed << setprecision(6) << l;
    return 0;
}
posted @ 2022-06-21 10:11  Zilliax  阅读(74)  评论(0)    收藏  举报