【发布时间】:2021-02-16 17:30:17
【问题描述】:
我在《Competitive Programmer's Handbook》https://cses.fi/book/book.pdf一书中遇到了这两种二分搜索的实现。
方法一:
int a = 0, b = n-1;
while (a <= b) {
int k = (a+b)/2;
if (array[k] == x) {
// x found at index k
}
if (array[k] > x)
b = k-1;
else
a = k+1;
}
方法二:
int k = 0;
for (int b = n/2; b >= 1; b /= 2){
while (k+b < n && array[k+b] <= x)
k += b;
}
if (array[k] == x){
// x found at index k
}
我猜方法 2 并不完全是二分搜索。 我知道 method 1 和 method 2 都有 O(log n) 复杂度。此外,方法 2 的代码更简单,因此可能会导致更少的错误。
我的问题是:
- 使用方法 2 时性能是否有任何提升?
- 方法 2 还有其他优势吗?
【问题讨论】:
-
方法 2 不是搜索的有效实现。将它与搜索的实现进行比较是没有任何意义的。你也可以比较二分查找和无操作。 no-op 比二分查找快,好的,接下来呢?
-
更少的代码和“更简单”(我不同意)并不意味着更少的错误。我认为第一个实现更容易理解,我可以立即看到发生了什么,所以我更喜欢这个实现。
-
方法2有效,几乎可以称为二分查找,但比看起来要复杂得多。
-
方法 2 绝对不简单(在实践中可能更慢),尽管它包含一个可以在二进制搜索之外应用的巧妙想法。
-
@YvesDaoust 当 n 为奇数时,将测试数组索引 a[k+b] 和 a[k+2b](在最坏的情况下)。
while确实需要是while并且不能是if。这就是为什么我认为代码具有欺骗性。
标签: algorithm performance binary-search coding-efficiency