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

这里写一些我对二分法的一些心得吧。好像大家写二分都会写得比较囧,上下界弄错~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;
}


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值