【ACWING】二分算法
二分查找
-
二分主要分为整数和实数两种问题,最麻烦的是整数二分问题,因为涉及到的边界问题比较多
-
二分大多是利用了单调性,有单调性的一定可以二分,但是有些二分可以没有单调性
-
二分的本质按y总说的,就是利用一个边界点,将其分为两部分,一部分满足一定条件,另一部分不满足这个条件
整数二分两种模板
注意下图中我没有标注mid
的位置。因为mid就是图中标记为true/false
的点
int l=0,r=len-1; //模板1 int bseach_1(int l,int r) { while(l<r) { int mid=l+r>>1; if(check(mid)) r=mid; else l=mid+1; } return l; } //模板2 int bseach_2(int l,int r) { while(l<r) { //这里一定要+1,不然若r=l+1,mid=l+r时,计算出来取下整,得到mid=l,这时候会死循环。 int mid=l+r+1>>1; if(check(mid)) l=mid; else r=mid-1; } return l; }
如何区分两种模板捏?
- 先写个
int mid=l+r>>1;
- 判断如何写check函数,(单调性用的多)
- 先画图判断
check(mid)==true
时r
,l
如何更新 - 确定完之后,根据L,R的更新方式,看看mid处是否+1
二分模板一定有解,如果有无解的情况,是题目设置的问题
二分会在l=r
时退出循环,最终判断就是看q[l]
的值是否是符合题意的,不符合即为无解
浮点数二分
浮点数二分的退出条件就是最后的区间小于一定程度,比如r-l<1e-8
的时候,我们认为q[l]
就是我们想要的值。
这里 1e-8
这个值是不定的,为了适应精度问题,一般多两位,比如说要求保留5位小数,最后要小于1e-7
而且这时候我们不需要考虑边界问题,所以只有一种模板
以求平方根的结果为例子
int main(){ double x; cin >> x; double l = 0,r = 10000; //第二种写法就是直接for(int i =0;i<100;i++) 这样子迭代下去 while(r-l>1e-8) { double mid =(l+r)/2; if (mid*mid>=x) r=mid; else l=mid; } printf("%lf\n",l); return 0; }
分类:
算法 / ACWING算法基础课
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步