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

问题描述 投票:0回答:2

以下是二进制搜索的略微修改的实现,它找到第一次出现的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;
}
java algorithm binary-search
2个回答
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
投票

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

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

© www.soinside.com 2019 - 2024. All rights reserved.