二分
目录
-
二分查找
-
二分答案
-
浮点二分
正文
二分查找
查找,即查找某个值在一个数列(有序)中的位置。
#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循环次数越多越精确
-
输出要看保留小数