【二分】关于二分法的一些总结

来源:互联网 发布:c语言如何清屏 编辑:程序博客网 时间:2024/05/12 02:35

这里写一些我对二分法的一些心得吧。好像大家写二分都会写得比较囧,上下界弄错~TLE什么的。

先写一下整数二分的:

【下面的程序都是在区间[l,r]上查找x,默认数据顺序非递减】

(1)二分查找区间内某个数字的下标(存在且唯一),不存在返回-1:

int search(int l,int r,int x){int mid;while (l<=r){mid=(l+r)>>1;if(a[mid]==x) return mid;if(a[mid]<x) l=mid+1;else r=mid-1;}return -1;}

这应该是最好写的二分了,注意条件l<=r不是l<r就好。没啥多说的,一看就明白了。

其实这个程序稍微改一下就可以变成查询某个数字出现的最早下标和最晚下标了。

(2)查询区间内<=x的最大值(有多个最大值时返回最靠右的坐标):

int search(int l,int r,int x){int mid;while (l<r){mid=(l+r+1)>>1;if(a[mid]<=x) l=mid;else r=mid-1;}return l;}

二分过程不多说,注意两点:

①假设要在[l,r]上查询那么建议传进去的参数是l-1.r,这样如果返回值为l-1则说明不存在<=x的值,或者可以选择在二分前选判断,确定存在解时再二分。

②mid=(l+r+1)>>1而不是mid=(l+r)>>1,如果取后一种方式的话,假设区间缩小到2、3,此时mid=2,此时如果a[mid]<=x成立那么l=mid,这样会变成死循环,所以要+1再除2。

(3)查询区间内>=x的最小值(有多个最小值时返回最靠左的坐标):

int search(int l,int r,int x){int mid;while (l<r){mid=(l+r)>>1;if(a[mid]>=x) r=mid;else l=mid+1;}return l;}

和(2)基本一样的程序,只是条件变成了r=mid和l=mid+1,因此mid要改成mid=(l+r)>>1,否则也会死循环。查询区间[l,r]则传参l,r+1,同样返回值为r+1时为无解。


这样只要控制好上下界和取中间的条件就可以1Y掉二分了。

实数上的二分比较好写,根据题目要求的精度控制一下边界就好,一般不会出现死循环的情况的。

while (fabs(r-l)>EPS)//EPS是题目要求的精度{mid=(l+r)/2;if(check(mid)) l=mid;else r=mid;}

可能有些题精度卡的比较欢乐可以采用循环的方式控制精度,事实上就算是在实数域二分的收敛也是非常快速的,将二分执行几百次基本上都可以收缩到解。

for(int i=1;i<=200;i++){mid=(l+r)/2;if(check(mid)) l=mid;else r=mid;}


原创粉丝点击