【二分查找】学习总结

二分查找: 

(1) 一般的二分查找:
         例如:找球号问题:  在某一国度里流行着一种游戏。游戏规则为:在一堆球中,每个球上都有一个整数编号i(0<=i<=100000000),编号可重复,现在说一个随机整数k(0<=k<=100000100),判断编号为k的球是否在这堆球中(存在为"YES",否则为"NO"),先答出者为胜。现在有一个人想玩玩这个游戏,但他又很懒。他希望你能帮助他取得胜利。
            这就是普通的二分查找,把所有的球号存入ans[ ]数组了,从小到大排序,然后二分查找,假设共n个球吧(数组中0----n-1)
           首先边界 fir=0,end=n-1,
           (1) 一旦fir<end不成立,即break,说明不存在 ;否则使mid=(fir+end)/2;
           (2)然后比较 ans[mid] 与 要查找是否存在的球号k,若相等 即输出 YES;
           (3)如果 ans [ mid ] > k, 则 fir 不变,end=mid-1;(ans[]是从小到大排序的,ans[mid]的球号大于k,那么mid后面的球号必定也大于k,故缩小近一半区间),转至(1)步;
           (4)如果 ans [ mid ] < k, 则end 不变, fir=mid-1 ;  (ans[]是从小到大排序的,ans[mid]的球号小雨k,那么mid前面的球号必定也小于k,~~~~转至(1)步;
          练习题目:http://acm.nyist.net/JudgeOnline/problem.php?pid=86;
          参考代码:http://blog.csdn.net/piaoyi0208/article/details/7270472;
(2) 二分查找求上界:
         看完一般的二分查找后,我们提一个问题,如果很多球号都是k,按照第一种写法(加上-找到球号时,返回该下标),会返回那个下标呢?第一个,最后一个?不难看出,都不是,怎样写能使 返回下标为 ans数组第一次出现k时的呢?若不存在k,在返回下标出插入k,后面的依次向后移一位,顺序不变!
//二分法求下界
#include<cstdio>
#include<cstring>
#include<iostream>
using namespace std;
int main()
{
	int ans[20]={0,1,2,3,3,3,3,3,4,5,7};
	//假设已经排好序了,查找球号 3
	int fir=0,end=10,mid;
	while(fir<end)
	{
		mid=(fir+end)/2;
		if(ans[mid]>=3)
			end=mid;
		else 
			fir=mid+1;
	}
	cout<<fir<<endl;
	/*输出结果是 3 */
}
分析: 一:ans[mid]=3;则说明以找到一个,左边可能还有也可能没有,区间从[ fir , end ]------->[ fir , mid ];
            二:ans[mid]>3;说明mid后得肯定不行,区间变为 [ fir , mid ];
            三:ans[mid]<3;说明mid前的和mid都不可行,区间变为 [mid+1,end];
          (将一和二合并一下就是上面的代码了)
(3) 二分查找求下界:

          同理,你也可以写一个求下界的代码,找到第一个比k大的数的位置。

//二分法求下界
#include<cstdio>
#include<cstring>
#include<iostream>
using namespace std;
int main()
{
	int ans[20]={0,1,2,3,3,3,3,3,4,5,7};
	//假设已经排好序了,查找球号 3
	int fir=0,end=10,mid;
	while(fir<end)
	{
		mid=(fir+end)/2;
		if(ans[mid]<=3)
			fir=mid+1;
		else 
			end=mid;
	}
	cout<<end<<endl;
	/*输出结果是 8 */
}
       最近做比赛时,遇到了用二分查找边界的问题,代码写的很郁闷,以前写过二分查找判断一个数在是否存在一组数据里,遇到查找边界问题,郁闷了~~~好好学习下,总结一下.......

你可能感兴趣的:(游戏)