一、基本思路
1、整数二分 —— 需要考虑边界问题,分为{mid,mid + 1}与{mid - 1,mid}两种
![在这里插入图片描述](https://i-blog.csdnimg.cn/blog_migrate/5c2bb674ff8fe4b3361d5db89a0b5c1d.jpeg#pic_center)
(1)创建check函数
- 创建check函数,确保满足某种性质,如左边满足,右边不满足;比如想找一个值为 >= x的索引,假如是升序排列,那就可以使用右半段进行分析。
(2)左段序列的右分界点求解
-
- mid = (left + right + 1) >> 1
mid的初始时没有 + 1 操作,后来是因为(l = mid),(l = r - 1)会导致死循环
-
- 进行 check(mid) 的检测
若为 true :mid的搜索区间变换为[ mid , r ], l = mid;
若为 false: mid的搜索区间变换为[ l , mid - 1 ], r = mid - 1 .
(3)右段序列的左分界点求解
-
- mid = (left + right ) >> 1
-
- 进行 check(mid) 的检测
若为 true :mid的搜索区间变换为[ l , mid ], r = mid;
若为 false: mid的搜索区间变换为[ mid + 1 , r ], l = mid + 1 .
2、浮点数二分法 ——不需要考虑边界问题
![请添加图片描述](https://i-blog.csdnimg.cn/blog_migrate/b5c81f9cb41fe2ae4bbe671ed93c8b5d.jpeg#pic_center)
- r - l <= 10.^(-n) ,需要在进行check的时候判断保留 n - 2 位小数
- 借用 求平方根的 算题求解:
- 判断 mid的平方和x的大小比较:
1.若为 ture:mid 搜索区间变为 [ l , mid ] , r = mid;
2.若为 false: mid 搜索区间变为[ mid , r ] ,l = mid。
二、Java、C语言模板实现
private static boolean check(int x){
}
private static int leftBinarySearch(int[] arr, int left, int right){
while (left < right){
int mid = arr[left + right >> 1];
if(check(mid)){
right = mid;
}else {
left = mid + 1;
}
}
return left;
}
private static int rightBinarySearch(int[] arr, int left, int right){
while (left < right){
int mid = left + right >> 1;
if(check(mid)){
right = mid;
}else {
left = mid + 1;
}
}
return left;
}
private static boolean check(double x) {
}
private static double EPS = 1e-6;
private static double floatBinarySearch(double left, double right) {
while (right - left > EPS) {
double mid = (left + right) / 2;
if (check(mid)) {
right = mid;
} else {
left = mid;
}
}
return left;
}
bool check(int x) {}
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;
}
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;
}
作者:yxc
链接:https:
来源:AcWing
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
bool check(double x) {}
double bsearch_3(double l, double r)
{
const double eps = 1e-6;
while (r - l > eps)
{
double mid = (l + r) / 2;
if (check(mid)) r = mid;
else l = mid;
}
return l;
}
三、注意事项
- 整数二分 —— 需要考虑边界问题,分为{mid,mid + 1}与{mid - 1,mid}两种
- 浮点数二分法 ——不需要考虑边界问题
- 二分法一般是用来搜索的
- 单调必然可以二分,二分不一定单调,比如求峰值问题,尚未涉及
- 具体步骤:
1.确定用二分,及使用左段还是右段模板
2.根据check确定mid新区间
3.考虑是否可以取到mid ,进行端点更新