一、整数二分(大多数情况)
整理:很有用,记住l = mid (对应+1)还是 r = mid(对应不+1)。——>男左女右,男1女0
后期:算法思想+刷题
核心思想:确定l 和 r(左右边界) 再算mid -> 画图(根据判断条件写出true和false情况)-> 加1还是不加1。
code:(r = mid)
bool check(int x) {/* ... */} // 检查x是否满足某种性质
// 区间[l, r]被划分成[l, mid]和[mid + 1, r]时使用:
int bsearch_1(int l, int r)
{
while (l < r)
{
int mid = l + r >> 1;
if (check(mid)) r = mid; // check()判断mid是否满足性质
else l = mid + 1;
}
return l;
}
code2:(l = mid)
// 区间[l, r]被划分成[l, mid - 1]和[mid, r]时使用:
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;
}
ps:int mid = l + (r - l +1 ) / 2;(leetcode这些写,>>1通不过)
二、浮点数二分(目前做leetcode没遇到过)
整理:比整数更简单。判断完条件后,mid直接等于左边或右边。(不需要过多关注这类题)
核心code:
bool check(double x) {/* ... */} // 检查x是否满足某种性质
double bsearch_3(double l, double r)
{
const double eps = 1e-6; // eps 表示精度,取决于题目对精度的要求
while (r - l > eps)
{
double mid = (l + r) / 2;
if (check(mid)) r = mid;
else l = mid;
}
return l;
}
完整code:
#include<iostream>
using namespace std;
const int N = 1e6 + 10;
int main()
{
double n;
//scanf("%lf", &n);
cin >> n;
if(n < 0)
{
cout << "-";
n = -n;
}
double l = 0., r = n; //step1
// if (n > -1 && n < 1) //BUG特判一下就好了
// {
// l = 0;
// r = 1;
// }
while (r - l > 1e-8) //step2二分
{
double mid = (l + r) / 2;
if (mid * mid * mid > n) r = mid;
else l = mid;
}
printf("%lf", l);
return 0;
}
ps:y总视频中忘记特判了,[0,1)区间的数值会wa,特判一下就好。