我正在尝试证明二进制搜索的复杂性。维基百科说,最糟糕的情况是log(n)。这意味着:
如果我有16个元素的数组,log(16)是4.我应该有最多4次调用来查找数组中的元素。
我的java代码:
class Main{
int search(int[] array, int number, int start, int end) {
System.out.println("Method call");
int half = (end - start) / 2;
if (array[start + half] == number) {
return array[start + half];
}
if (array[start + half] < number) {
return search(array, number, start + half, end);
} else {
return search(array, number, start, end - half);
}
}
public static void main(String[] args) {
int[] array = new int[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 };
for (int i : array) {
System.out.println(i);
new Main().search(array, i, 0, array.length);
}
}
}
Ideaone代码:http://ideone.com/8Sll9n
,输出为:
1
Method call
Method call
Method call
Method call
Method call
2
Method call
Method call
Method call
Method call
3
Method call
Method call
Method call
4
Method call
Method call
Method call
Method call
5
Method call
Method call
6
Method call
Method call
Method call
Method call
7
Method call
Method call
Method call
8
Method call
Method call
Method call
Method call
9
Method call
10
Method call
Method call
Method call
Method call
11
Method call
Method call
Method call
12
Method call
Method call
Method call
Method call
13
Method call
Method call
14
Method call
Method call
Method call
Method call
15
Method call
Method call
Method call
16
Method call
Method call
Method call
Method call
一切都很好,除了搜索1.我有5个“方法调用”,这意味着5大于log(16)。
我的假设是,我可能错误地计算了电话。有人能告诉我我哪里错了吗?
答案 0 :(得分:5)
n
的大小为a > 1
的输入的二进制搜索的复杂性为a=2
的 O(log a n)。算法的本质表明f(n)= O(g(n))
,因为在每次迭代时搜索空间都减半。
您提供的代码也正常。关于算法复杂性的混淆已经发生,因为您忽略了Big-Oh表示复杂性中隐藏的常量。
声明f(n) ≤ cg(n)
表示c
。在您的情况下,您忘记承认此常量c
。 n < 1000000000
可能会非常大到 100000000000 或小到 0.000000001 。这是与Big-Oh表示法相关的一个问题。对于许多实际目的,由于涉及非常大或小的常数,渐近更复杂的算法可能会执行渐近更简单的算法。
例如,与算法 h = O(n 2 )相比,算法 g = O(1000000000 n)将提供较差的性能,f
。
因此,结论是,由于隐藏常数的参与,您无法仅通过计算执行的指令数来证明算法的复杂性。你需要有严格的数学方法来获得证据。
例如,对输入大小n=10
执行 100 指令的算法{{1}}可以是,
O(n)如果c 10 , f(n)= O(10 n)。
O(n 2 )如果c 1 , f(n)= O(1 n 2 )强>
O(n 3 )如果c 0.1 , f(n)= O(0.1 n 3 )强>
答案 1 :(得分:2)
在Big O表示法中,常量可以被忽略,因为随着输入N的值增加,由于常数因子而不会有任何复杂性的变化,并且它变得可以忽略不计。
在这里,在二进制搜索中,发生了额外的呼叫。即使你拿了十亿个数字,它仍然是最多1个额外的电话。因此它变得可以忽略不计,你无需计算。