二分

整数二分

整数二分是一种查找算法,用某个条件将序列划分为两部分,查找右侧子序列的左端点。

(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应该初始化为nl应该初始化为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-1l应该初始化为-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)。