二分思想的本质
本质思想
通过二分法查找有序数列中某个数字的下标,只是二分法的一种应用,二分法的本质是找到性质的边界。
查找有序数列的数字x,本质是x将数组分成了两个性质,x左边的数满足性质1:小于等于x;x右边的数满足性质2:大于等于x。
在该情境下,无论是左边性质还是右边性质,边界都是一样的(假设序列中只有一个x)。这里假设通过求左边性质的边界,达到求x下标的目的。
int binary_search(int a[], l, r, x) {
while (l < r) {
int mid = (l + r + 1) >> 1;
// 性质: <=x,检查mid是否满足性质
if (a[mid] <= x) l = mid;
else r = mid - 1;
}
return a[l];
}
这里mid = (l + r + 1) >> 1,是为了防止出现死循环。如果不加1,当l = r - 1时,mid=l,而接下来的判断可能会使得l = mid,就会发生mid一直等于l的情况,发生死循环。
处理边界
对于二分法,思想不难,但是边界问题很难处理,yxc提供了一种模版非常好用,上面的代码也是根据模版所写。
以下模版适用于整数二分:
// 求右边性质边界
int bsearch_1(int l, int r)
{
while (l < r)
{
int mid = l + r >> 1;
if (check(mid)) r = mid; // check()判断mid是否满足性质
else l = mid + 1;
}
return l;
}
// 求左边性质边界
int bsearch_2(int l, int r)
{
while (l < r)
{
int mid = l + r + 1 >> 1;
if (check(mid)) l = mid;
else r = mid - 1;
}
return l;
}