二分查找总结

二分是一个很基础的算法,但是我到现在每次用时,对于边界都还有一些不确定。于是做一个总结,希望自己不再迷糊。
整理内容借鉴了网上搜到的一篇不错的博文,但是代码什么的还是我自己写的。不过本着尊重博主的原则,我还是放一下链接: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),纯二分, 题目链接:传送门
2、Cable master(来源:POJ 1064)链接:传送门
3、Monthly Expense(来源:POJ 3273)链接:传送门
4、关押罪犯 (NOIP2010提高组),纯二分,唯一的难度在于check。
5、聪明的质监员(NOIP2011提高组),纯二分,附上我的讲解:[NOIP2011][二分]聪明的质监员
6、借教室(NOIP2012提高组),二分加线段树,有一定难度。
7、cut 讲解链接:[NOIP模拟][二分]cut

以上题目,排名顺序与难度大小无关(>_<)如果你没有评测渠道,我又没有附链接,那么可以去洛谷评测,NOIP题它都有。

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值