二分算法
二分查找
要求
数据是有序且单调的
模板
从左到右
while (l < r)
{
int mid = l + r >> 1; //(l+r)/2
if (check(mid)) r = mid; // check()判断mid是否满足性质 //arr[mid] >= x
else l = mid + 1;
}
从右到左
while (l < r)
{
int mid = l + r + 1 >> 1; //(l+r+1)/2
if (check(mid)) l = mid; //arr[mid] <= x
else r = mid - 1;
}
若存在所找数不存在的情况只需要在循环结束后进行判断:
if(arr[mid] != num) //...
浮点二分
while(r-l>1e-5) //需要一个精度保证,一般比要求的多两位即可(经验)
{
double mid = (l+r)/2;
if(check(mid)) l=mid; //或r=mid;
else r=mid; //或l=mid;
}
二分答案
要求
- 答案属于一个区间,且区间是单调的
- 直接搜索不好搜,但是容易判断一个答案可行不可行
另一个典型特征:求…最大值的最小,求…最小值的最大
模板
求…最大值的最小:及二分答案的时候,判断条件满足后,尽量让答案往前靠,(即:让r=mid)对应模板从左到右
求…最小值的最大:及二分答案的时候,判断条件满足后,尽量让答案往后靠,(即:让l=mid)对应模板从右到左
解题方向
最短距离最大化问题:保证任意区间距离要比最短距离mid大或相等(这样,mid才是最短距离)即:区间的距离>=mid
最长距离最小化问题:保证任意区间距离要比最大距离mid小或相等(这样,mid才是最大距离)即:区间的距离<=mid