注:二分通常与单调性紧密相连,但是二分并非完全依赖单调性。
二分的本质是寻找出一个刚好符合,或不符合某个性质的点,将区间分为两半,涉及边界问题,如果处理不当,很可能进入死循环等局面,下面两个模板可以有效应对。
1.整数二分
int l = 0, r = n - 1;
//模板一
while (l < r)
{
int mid = (l + r) >> 1; //差别之处
if (arr[mid] >= x) //判断条件为ture即可
{
r = mid; //判断mid那一步不+1的关键
}
else
{
l = mid + 1;
}
}
//模板二
while (l < r)
{
int mid = (l + r + 1) >> 1; //差别之处
if (arr[mid] <= x) //判断条件为ture即可
{
l = mid; //判断mid那一步+1的关键
}
else
{
r = mid - 1;
}
}
2.浮点数二分
浮点数不存在边界问题,所以直接循环查找即可,比较简单。
double l = 0, r = n//右边界;
for (int i = 0; i < 1000; i++)
{
double mid = (l + r) / 2;
if (mid * mid * mid <= n)
{
l = mid;
}
else
{
r = mid;
}
}
3.结语
在需要用到查找的地方,可以考虑用上二分的思想。模板是可以背的,但是还是那句话,思想是最重要的,背模板只是为了写的速度。