整数二分是一种查找算法,用某个条件将序列划分为两部分,查找右侧子序列的左端点。
(1)设置check条件,使得右侧所有元素全部满足check条件(左侧不满足);
(2)选择中间坐标m = (l+r)/2
,将序列划分为[l, m]
和[m+1, r]
两部分;
(3)若check(m)
为true,要找的端点在[l, m]
中,否则在[m+1, r]
中,迭代处理,直到找到右侧子序列的左端点(满足check条件的最左端)。
bool check(int x) { /* ... */ }
int BinarySearch(int l, int r) {
while (l < r) {
int m = (l+r)/2;
if (check(m)) r = m;
else l = m+1;
}
return l; // 返回l或r均可
}
对于数组长度为n
的数组arr[0...n-1]
,二分查找右侧子序列的左端点时,r
应该初始化为n
,l
应该初始化为0
。
注解:
(1)也可查找左侧子序列的右端点:
设置check条件,使得左侧所有元素全部满足check条件(右侧不满足);
选择中间坐标m = (l+r+1)/2
,将序列划分为[l, m-1]
和[m, r]
两部分;
若check(m)
为true,要找的端点在[m, r]
中,否则在[l, m-1]
中,迭代处理,直到找到左侧子序列的右端点(满足check条件的最右端)。
bool check(int x) { /* ... */ }
int BinarySearch(int l, int r) {
while (l < r) {
int m = (l+r+1)/2;
if (check(m)) l = m;
else r = m-1;
}
return r; // 返回l或r均可
}
对于数组长度为n
的数组arr[0...n-1]
,二分查找左侧子序列的右端点时,r
应该初始化为n-1
,l
应该初始化为-1
。
浮点数二分用来近似计算,用某个条件将序列划分为两部分,计算两部分分界点的近似值。
(1)设置check条件,使得右侧所有元素全部满足check条件(左侧不满足);
(2)选择中间坐标m = (l+r)/2
,将序列划分为[l, m]
和[m, r]
两部分;
(3)若check(m)
为true,要找的分界点在[l, m]
中,否则在[m, r]
中,迭代处理,直到r-l满足精度要求。
bool check(double x) { /* ... */ }
double BinarySearch(double l, double r) {
while (r-l > eps) {
double m = (l+r)/2;
if (check(m)) r = m;
else l = m;
}
return l; // 返回l或r均可
}
注解:
(1)要保证整数位和小数前6位准确,eps至少要设置为1e-8(因为C++中float和double默认都是显示6位);如果对精度有更高要求,保留小数点后k位,就将eps设置为1e-(k+2)。