返回顶部

二分

目录

  • 二分查找

  • 二分答案

  • 浮点二分

正文

二分查找

查找,即查找某个值在一个数列(有序)中的位置。

#include <bits/stdc++.h>
using namespace std;
int a[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
int main()
{
    int ans;
    cin >> ans;
    int l = 1, r = 10;
    int mid;
    while (l <= r)
    {
        mid = (l + r) / 2;
        if (ans < a[mid]) // 大右小左
        {
            r = mid - 1; // ?
        }
        else
        {
            l = mid + 1;
        }
    }
    cout << mid;
    return 0;
}

如上代码:

  • 定义a数组为1~10的有序数组

  • ans为要查找的值

  • l,r为查找的边界

  • mid为二分查找的基准值

  • 判断查找的值是否比基准值大?若大,则边界向右缩小;否则,向左缩小。

  • mid最终即为找到的位置

测试:

输入:5
输出:4

数组下标从0开始,5排第四,正确。

二分答案

答案,即使用二分的办法来求解答案。

以"木材加工"这道题为例:


#include <bits/stdc++.h>
using namespace std;
int n, k;
int a[1000005];

bool check(int x)
{
    int ans = 0;
    for (int i = 1; i <= n; i++)
        ans += a[i] / x; // 切
    return ans >= k;     // 是否大于k满足条件?
}

int main()
{
    cin >> n >> k;
    for (int i = 1; i <= n; ++i)
        cin >> a[i];

    int l = 0;
    int r = 2147483647; // 木材加工的最大值!

    while (l <= r)
    {
        int mid = (l + r) / 2;
        if (check(mid))
            l = mid;
        else
            r = mid; // 基本框架
    }
    cout << l << endl; // 最小
    // if (check(r))
    //     cout << r << endl;
    // else if (check(l))
    //     cout << l << endl;
    // else
    //     cout << -1 << endl;
    return 0;
}

此类二分问题主要在于check函数的编写,如何判断该不该二分答案?

还要注意r值的取法?

浮点二分

以"数的三次方根"为例:

#include <bits/stdc++.h>
using namespace std;

int main()
{
    double n;
    cin >> n;
    double l = -100, r = 100;
    for (int i = 0; i < 100; ++i)
    {
        double mid = (l + r) / 2;
        if (mid * mid * mid >= n)
        {
            r = mid;
        }
        else
        {
            l = mid;
        }
    }
    printf("%.2f", l);
}
  • l和r是已经根据题目数据确定的

  • for循环次数越多越精确

  • 输出要看保留小数

posted @ 2022-05-08 22:07  zrc4889  阅读(22)  评论(0编辑  收藏  举报