二分查找

2017-05-09  本文已影响0人  RobotBerry

输入

输出

元素在容器中的位置

时间复杂度

O(logn)

空间复杂度

O(1)

例子

容器:1 3 5 8 9 10 15 27
元素:9
返回值:4

find

为了简单起见,元素类型限定为int,容器为vector。后面可以定义成模板函数,支持任意元素类型和任意支持前向迭代器的容器。

// 二分搜索,从容器a中查找元素val
// 返回元素出现的位置。如果不存在,返回-1
int binarySearch(const vector<int> &a, int val) {
    int begin = 0, end = a.size() - 1, mid;
    while (begin <= end) {
        mid = (begin + end) / 2;
        if (a[mid] < val)
            begin = mid + 1;
        else if (a[mid] > val)
            end = mid - 1;
        else
            return mid;
    }
    return -1;
}

变型

之前的二分查找是查找元素的位置,要求精确匹配元素的值:如果存在就返回位置,如果不存在就返回-1. 其实有时候我们不需要进行精确匹配。例如对于容器:1 3 5 8 9 10 15 27,我们要查找7,显然7在容器里不存在,但是我们还是希望算法能够返回一个大概的位置。这个位置可能有两个:5或者8。5是7的下界(lower bound),8是7的上界(upper bound)。

还有一种情况,假设容器允许出现重复元素,例如1 3 5 5 5 8 9 10 15 27。这时5的下界就是下标为2的5,5的下界就是下标为4的5。

lower bound

// 二分下界搜索,在容器a中查找元素val的下界
// 如果下界不存在,返回-1
int binarySearchLowerBound(const vector<int> &a, int val) {
    if (val < a.front()) return -1;
    int begin = 0, end = a.size() - 1, mid;
    while (begin < end) {
        mid = (begin + end) / 2;
        if (a[mid] < val)
            begin = mid + 1;
        else
            end = mid;
    }
    return a[begin] == val ? begin : begin - 1;
}

upper bound

// 二分上界搜索,在容器a中查找元素val的上界
// 如果上界不存在,返回-1
int binarySearchUpperBound(const vector<int> &a, int val) {
    if (val > a.back()) return -1;
    int begin = 0, end = a.size() - 1, mid;
    while (begin < end) {
        mid = (begin + end) / 2 + 1;
        if (a[mid] > val)
            end = mid - 1;
        else
            begin = mid;
    }
    return a[begin] == val ? begin : begin + 1;
}
上一篇下一篇

猜你喜欢

热点阅读