二分搜索的深化

二分搜索也叫折半搜索,算法本质是分而治之,通过不断缩小范围来搜索。二分搜索只实用于有序数组。

int binarySearch(int[] x, final int n) {
    if (x == null || x.length == 0) {
        return -1;
    }
    int p = 0, q = x.length - 1;
    while (p <= q) {
        int m = p + (q - p) / 2;
        if (x[m] == n) {
            return m;
        } else if (x[m] < n) {
            p = m + 1;
        } else {
            q = m - 1;
        }
    }
    return -1;
}

测试用例需要考虑的边界情况:长度是1或2的数组,处理处理不好,可能出现死循环。

从这段代码可以看出,排序的意义之一就是为了便于搜索。

下面给出递归版本:

int binarySearch(int[] x, final int n, int p, int q) {
    if (x == null || x.length == 0 || p > q) {
        return -1;
    }
    int m = p + (q - p) / 2;
    if (x[m] == n) {
        return m;
    } else if (x[m] < n) {
        return binarySearch(x, n, m + 1, q);
    } else {
        return binarySearch(x, n, p, m - 1);
    } 
}

在一个线性结构中,可能出现重复的元素,返回的下表,可能是随机一个索引。现在期望返回下表最小的索引:

int binarySearchForFirstKey(int[] x, final int n) {
    if (x == null || x.length == 0) {
        return -1;
    }
    int p = 0, q = x.length - 1;
    while (p <= q) {
        int m = p + (q - p) / 2;
        if (x[m] == n) {
            if (m == 0 || x[m] > x[m - 1]) {
                return m;
            } else {
                q = m - 1;
            }
        } else if (x[m] < n) {
            p = m + 1;
        } else {
            q = m - 1;
        }
    }
    return -1;
}

至于返回最右索引的代码省略。

参考:《剑指offer》38题

你可能感兴趣的:(二分搜索的深化)