这个修改后的二进制搜索实现仍然是O(log n)吗?

时间:2017-12-29 16:41:31

标签: java algorithm binary-search

以下是二进制搜索的略微修改的实现,它找到第一次出现的Integer键。

这仍然是O(log n)吗?我在确定在最坏的情况下是否会成为O(n)时遇到一些麻烦。

private static Integer lowestRank(Integer[] a, Integer key) {
    Integer lo = 0;
    Integer hi = a.length - 1;

    while (lo <= hi) {
        Integer mid = lo + ((hi - lo) / 2);
        if (key.compareTo(a[mid]) > 0) {
            lo = mid + 1;
        } else if (key.compareTo(a[mid]) < 0) {
            hi = mid - 1;

        // Modified here to return the first occurrence of the key, if it exists
        } else if (lo < mid) {
            hi = mid;

        } else {
            return mid;
        }
    }

    return -1;
}

2 个答案:

答案 0 :(得分:1)

是的,它仍然是O(log(n))。第三个条件语句仅在key.compareTo(a[mid]) == 0(因为前两个条件消除不等式情况)和lo < mid时才运行。

如果密钥在数组中只存在一次,则此分支最多只发生一次;如果密钥不存在,则根本不会发生。由于条件本身以及条件体中的所有内容都是恒定时间操作,因此运行时间仍为O(log(n))

如果密钥多次出现怎么办?首先,无论如何,这个条件分支的目的是什么:

else if (lo < mid) {
    hi = mid;
}

如果lo < mid,则表示我们尚未扫描整个列表范围。因此,我们设置hi = mid,从而将mid设置为我们搜索的上限。

因此,即使密钥多次出现,搜索范围也会在每次迭代时减半。

答案 1 :(得分:1)

假设我们将单个语句建模为 O(1),那么我们的整体复杂性由循环迭代次数决定。

如果我们将范围([lo, hi))减少每次迭代的恒定量(平均),则迭代次数只能是 O(n)。在所有三个相关案例中,显然情况并非如此 - 平均范围总是减半。

相关问题