整数二分与浮点二分 (二分查找)
二分查找就是每次讲范围缩小一半从而不断逼近所求值
就像我们高中数学二分零点 然后判断一正一负
然后分两种情况 要么左边和mid 要么mid和右边
1.整数二分(头疼的就是边界问题)
有两种情况
第一种是我们要往左边找答案
第二种是我们要往右边找答案
说一下mid的求法 一开始默认写成l+r>>1 //(l+r)/2
首先说第一种,顾名思义就是我们要找的答案在左边,所以就往左边找答案。
如果mid处值大于在左边的答案 q[mid]>=x 就符合条件 那么mid就是新的右边界 r=mid 答案在[l,mid]里
否则mid就是左边界 l=mid+1 (因为mid处小于x 已经不符合了,所以答案在[mid+1,r]里
这里的mid = l+r>>1 不用变
如果没有找到你要的那个答案 比如>=x 如果你要找到最左边这个x但是没有 这个模板会返回>=x的第一个最小的那个数
bool check(int mid)
{
if(a[mid]>=x) return true;
return false;
}
while(l<r)
{
int mid=l+r>>1;
if(check(mid)) r=mid;
else l=mid+1;
}
第二种,顾名思义就是我们要找的答案在右边,所以就往右边找答案。
如果mid处值x小于等于在右边的答案 q[mid]<=x 就符合条件 那么mid就是新的左边界 l=mid 答案在[mid,r]里
否则mid就是右边界 r=mid-1 (因为mid处大于x 已经不符合了,所以答案在[l,mid-1]里
这里的mid要改成l+r+1>>1
(原因是当我们一段区间里l等于r-1时候 如果mid是l+r>>1的话 就会向下取整 mid结果就是r-1 然后这时候新的左边界l=mid
就会导致l=r-1 然后新的区间还是[r-1,r] 会进入死循环)
如果没有找到你要的那个答案 比如<=x 如果你要找到最右边这个x但是没有 这个模板会返回<=x的第一个最大的那个数
bool check(int mid)
{
if(a[mid]<=x) return true;
return false;
}
while(l<r)
{
int mid=l+r+1>>1;
if(check(mid))l=mid;
else
r=mid-1;
}
以上就是两个整数二分的模板 根据情况套用就可以省去为边界问题的烦恼
2.浮点二分
最简单的一种,因为我们数学上经常也是在实数范围找
以AcWing 790. 数的三次方根为例题演示
给定一个浮点数 n,求它的三次方根。
输入格式
共一行,包含一个浮点数 n。
输出格式
共一行,包含一个浮点数,表示问题的解。
注意,结果保留 6位小数。
数据范围
−10000≤n≤10000
double l=-10000,r=10000;//答案区间可以优化一下 因为是开3次方 肯定比n这个小
while(r-l>=1e-8)//这里标记一下我也不是很理解这里是控制精度的 保留多少位就在10的-位数这个基础上多乘1的-2
{
double mid=(l+r)/2;//整数才能移位
if(mid*mid*mid>=n) r=mid;
else l=mid;
}
没有边界问题的烦恼啦 就保证精度就可以了