二分查找总结

来源:互联网 发布:nex5t 软件b 编辑:程序博客网 时间:2024/05/27 19:27

二分是一个很基础的算法,但是我到现在每次用时,对于边界都还有一些不确定。于是做一个总结,希望自己不再迷糊。
整理内容借鉴了网上搜到的一篇不错的博文,但是代码什么的还是我自己写的。不过本着尊重博主的原则,我还是放一下链接:http://www.cnblogs.com/luoxn28/p/5767571.html(我的和他的还是不同的···)
二分的几种写法:
我们假设一个最简单的环境,对于数x,按要求询问它在一个数组a(假设从小到大)里的位置,数组个数为n。
1.查找最后一个小于x的数的位置
常见的一种要求。返回小于x的其中的最右边一个数的下标。
代码:

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

2.查找最后一个小于或等于x的数的位置
返回小于或等于x的其中的最右边一个数的下标。

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

3.查找第一个大于x的数的位置
常见的一种要求。返回大于x的其中的最左边一个数的下标。

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

4.查找第一个大于或等于x的数的位置
常见的一种要求。返回大于或等于x的其中的最左边一个数的下标。

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

二分总结:
以上几种写法是比较常见基础的。我们会发现二分的写法有几个套路:while(l<=r),l=mid+1,r=mid-1等等。但最重要的是根据题目要求来定边界的处理,有时候你二分的并不一定是整数,更多情况下,你的判断mid并不只是简单的判断大小,可能会写一大堆复杂的判断过程。
二分之外,还有三分,可以看做是对二分的一种改进,适用于单峰函数。
练习题:
附几道二分练习题。
1、Aggressive cows(来源:POJ2456),纯二分, 题目链接:http://poj.org/problem?id=2456。
2、Cable master(来源:POJ 1064)链接:http://poj.org/problem?id=1064
3、Monthly Expense(来源:POJ 3273)链接: http://poj.org/problem?id=3273
4、关押罪犯 (NOIP2010提高组),纯二分,唯一的难度在于check。
5、聪明的质监员(NOIP2011提高组),纯二分,附上我的讲解:http://blog.csdn.net/g19zwk/article/details/77371970。
6、借教室(NOIP2012提高组),二分加线段树,有一定难度。
7、传送带(来源:1857: [Scoi2010])链接:http://www.lydsy.com/JudgeOnline/problem.php?id=1857,这是一道三分题。
以上题目,排名顺序与难度大小无关(>_<)如果你没有评测渠道,我又没有附链接,那么可以去洛谷评测,NOIP题它都有。

转载来源:千古的博客

本篇完。

原创粉丝点击