Java:二进制搜索实现无法使用延迟检测相等性

Java: Binary Search Implementation not working using Deferred detection of equality

我正在尝试实施二进制搜索 Java 版本。从维基百科 http://en.wikipedia.org/wiki/Binary_search_algorithm#Deferred_detection_of_equality 我注意到延迟检测相等版本。它正在使用该算法。但是,当我尝试像这样更改 if 条件表达式时:

    public int bsearch1(int[] numbers, int key, int start){
    int L = start, R = numbers.length - 1;
    while(L < R){
        //find the mid point value
        int mid = (L + R) / 2;
        if (numbers[mid] >key){
            //move to left
            R = mid - 1;
        } else{
            // move to right, here numbers[mid] <= key
            L = mid;
        }
    }
    return (L == R && numbers[L] == key) ? L : -1;
}

运行不正常,进入死循环。你们有什么想法吗?太感谢了。

您错过了您 link 访问的 Wiki 中 assert 的效果。

它指出:

code must guarantee the interval is reduced at each iteration

如果您的 mid >= R,您必须退出。

已添加

Wiki 实际上有点误导,因为它表明仅确保 mid < r 就足够了——事实并非如此。您还必须防范 mid == min(假设您有一个 4 条目数组,并且 l = 2r = 3mid 会变成 2 并停留在那里因为整数数学中的 2 + 3 = 55 / 2 = 2)。

解决方案是在 / 2 之后向上舍入 ,这可以通过以下方式轻松实现:

  int mid = (l + r + 1) / 2;

最终更正和整理的代码有点像这样:

public int binarySearch(int[] numbers, int key, int start) {
    int l = start, r = numbers.length - 1;
    while (l < r) {
        //find the mid point value
        int mid = (l + r + 1) / 2;
        if (numbers[mid] > key) {
            //move to left
            r = mid - 1;
        } else {
            // move to right, here numbers[mid] <= key
            l = mid;
        }
    }
    return (l == r && numbers[l] == key) ? l : -1;
}

public void test() {
    int[] numbers = new int[]{1, 2, 5, 6};
    for (int i = 0; i < 9; i++) {
        System.out.println("Searching for " + i);
        System.out.println("Found at " + binarySearch(numbers, i, 0));
    }
}

有一个非常相似的算法 here 表明正确的方法更像是:

public int binarySearch(int[] numbers, int key) {
    int low = 0, high = numbers.length;
    while (low < high) {
        int mid = (low + high) / 2;
        if (numbers[mid] < key) {
            low = mid + 1;
        } else {
            high = mid;
        }
    }
    return low < numbers.length && numbers[low] == key ? low : -1;
}

这对 high = max + 1 的边界条件采用了一种略有不同的方法,并且也很完美。