二分
分为两个部分
1.整数二分
2.浮点数二分
整数二分
有单调性一定可以二分
可以二分的题目不一定必须要有单调性
所以二分的本质并不是单调性
给定一个性质在区间右半边满足在区间左半边不满足
如果可以找到这样一个性质使得整个区间一分为二,一半满足一半不满足
二分可以寻找这两个区间的边界
二分不同的区域使用不同的模板
整数二分:
l |---------------___________________| r
既可以找到'---'区域的右边界,也可以找到'___'区域的左边界
第一个模板(寻找’—'区域的右边界)
如何二分出来'---'边界点
(1) 中间值
mid=(l+r+1)/2;//如果不加1的话,当l=r-1的时候就会变成死循环
if(check(mid)) //是否满足'---'性质
true: mid一定在'---'区间里,答案在[mid,r],mid可能是答案
l=mid
false: 答案在[l,mid-1], r=mid-1
第二个模板(寻找’___'区域的左边界)
mid=(l+r)/2;
if(check(mid))
true: [l,mid] r=mid
false; [mid+1,r] l=mid+1
采用哪个模板:
先写一个Mid
根据Check思考如何选择模板
先不写加1 想想二分的哪个边界,然后写判断,如果是true在哪个边界,
两种二分的方式,一种方式补上加一,一种不用补上加一,二分的哪个边界,性质是什么
二分算法一定可以把边界二分出来,如果题目中有找不到结果的情况,那么需要
按相应的情况去做一个判断。
浮点数二分:
边界问题
答案在[l,r]
通过二分找到边界出来
浮点数不存在整除问题
每一次通过中间点查看是否找到答案,当区间长度足够小的话可以认为足够小了
例子:
开平方
int main() {
int x;
scanf("%d",&x);
double l=0,r=x;
while(r-l>1e-8) //bi比要求的有效位数多2
{
double mid=(l+r)/2;
if(mid*mid>=x)
r=mid;
else
l=mid;
}
cout<<l<<endl;
return 0;
}
第二种写法
for(int i=0;i<100;i++)//不管如何迭代一百次
{
double mid=(l+r)/2;
if(mid*mid>=x)
r=mid;
else
l=mid;
}