这个修改后的二分搜索实现仍然是 O(log n) 吗?
Is this modified implementation of binary search still O(log n)?
以下是查找第一次出现的 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;
}
对,还是O(log(n))
。第三个条件语句仅在 key.compareTo(a[mid]) == 0
(因为前两个条件消除了不等式情况)和 lo < mid
.
时运行
如果键在数组中只存在一次,则该分支最多发生一次;如果密钥不存在,则根本不会发生。由于条件本身以及条件主体中的所有内容都是恒定时间操作,因此 运行 时间保持 O(log(n))
.
key出现多次怎么办?首先,这个条件分支的目的是什么:
else if (lo < mid) {
hi = mid;
}
如果lo < mid
,则表示我们还没有扫描列表的全部范围。因此,我们设置 hi = mid
,从而将 mid
作为我们搜索的上限。
因此,即使key出现多次,搜索范围也会在每次迭代时减半。
假设我们将单个语句建模为 O(1),那么我们的整体复杂度取决于循环迭代次数。
迭代次数只能是 O(n) 如果我们每次迭代将范围 ([lo, hi)
) 缩小一个常数(平均) .在所有三个相关案例中,显然情况并非如此 - 范围总是平均减半。
以下是查找第一次出现的 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;
}
对,还是O(log(n))
。第三个条件语句仅在 key.compareTo(a[mid]) == 0
(因为前两个条件消除了不等式情况)和 lo < mid
.
如果键在数组中只存在一次,则该分支最多发生一次;如果密钥不存在,则根本不会发生。由于条件本身以及条件主体中的所有内容都是恒定时间操作,因此 运行 时间保持 O(log(n))
.
key出现多次怎么办?首先,这个条件分支的目的是什么:
else if (lo < mid) {
hi = mid;
}
如果lo < mid
,则表示我们还没有扫描列表的全部范围。因此,我们设置 hi = mid
,从而将 mid
作为我们搜索的上限。
因此,即使key出现多次,搜索范围也会在每次迭代时减半。
假设我们将单个语句建模为 O(1),那么我们的整体复杂度取决于循环迭代次数。
迭代次数只能是 O(n) 如果我们每次迭代将范围 ([lo, hi)
) 缩小一个常数(平均) .在所有三个相关案例中,显然情况并非如此 - 范围总是平均减半。