二分法总结

◇◆丶佛笑我妖孽 提交于 2020-01-12 13:54:00

一.使用二分需要满足两个条件:有界性和单调性

有界性:有界二分答案应在一个闭区间上进行;
单调性:问题的解分布在一个区间上,这里有很多不合法的解,也有很多合法的解.考虑所有合法(可行)解,目标是从这些可行解中找到一个最优的作为答案. 注意到最优解一定可行,但可行解不一定最优.假设整个序列具有单调性,一般地,若一个数xx为合法解,则对x<x{\forall}x'<x,都是合法解.若有一个数yy是非法解,则对y>y{\forall}y'>y,都是非法解.正是因为有单调性的存在,才使得每次舍弃解区间的一半[l,mid][l,mid][mid,r][mid,r]这种优化是正确的,因为保证舍弃的区间一定是非法解区间.

二.二分法模板(二分答案与二分查找)

二分法总是可以分成"求满足某条件的最大值"与"满足条件的最小值"两种情况,
其中"某条件"常常被封装成check()函数 判断当前解是否可行.
(1)整数域的二分

//寻找满足条件的最小值
int l=0,r=n,mid;
while (l<r)
{
	mid=(l+r)/2;
	
	if (check(mid))
		r=mid;
	else
		l=mid+1;
}
//l即为所求
//寻找满足条件的最大值
int l=0,r=n,mid;
while (l<r)
{
	mid=(l+r+1)/2;
	
	if (check(mid))
		l=mid;
	else
		r=mid-1;
}
//l即为所求

(2)实数域的二分
与整数域上的二分相比有变动,求mid时不在加1;else后也不再加1或减1;

三.二分法的应用:二分查找.查找有序序列中的元素,返回下标

1.如:求序列中第一个大于x的元素的下标,等价于寻找满足x<a[mid]的最小mid
求序列最后一个小于等于x的元素的下标,等价于寻找满足x>=a[mid]的最大mid

2.事实上,C++中封装了两个函数,可以方便地实现二分查找
upper_bound()返回第一个大于某元素的下标;等价于寻找满足a[mid]>x的最小值
lower_bound()返回第一个大于等于元素的下标;等价于寻找满足a[mid]>=x的最小值
如:

int tmp = upper_bound(a, a + 5, 7) - a;
/*data:
9
20 20 40 40 40 60 60 80 80
9
15 20 35 40 45 60 75 80 85*/

四.二分法的应用:二分答案.

如:最大(小)值最小(大)

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!