准备考试我在旧考试中遇到过这个问题:
此函数的最坏情况/大O复杂度是什么:
float foo(float[] A) {
int n = A.length;
if (n == 1) return A[0];
float[] A1 = new float[n/2];
float[] A2 = new float[n/2];
float[] A3 = new float[n/2];
float[] A4 = new float[n/2];
for (i = 0; i <= (n/2)-1; i++) {
for (j = 0; j <= (n/2)-1; j++) {
A1[i] = A[i];
A2[i] = A[i+j];
A3[i] = A[n/2+j];
A4[i] = A[j];
}
}
return foo(A1)
+ foo(A2)
+ foo(A3)
+ foo(A4);
}
(是的,代码没有意义,但这正是它的编写方式)。
让我感到震惊的是,每个递归级别的n的总大小会加倍,但建议的答案(最终结果为O(log n * n^2)
)会忽略该部分。我误解了什么吗?
编辑:用语法正确(但仍然是荒谬的)代码替换半伪代码。
答案 0 :(得分:2)
如果你解决了这种递归关系,你就能确定复杂性。
T(n) = 4T(n/2) + O(n²)
使用
T(1) = c
答案 1 :(得分:1)
好的,我终于明白了。
每次我们递归时,我们执行的函数调用次数是上次的4倍,因此如果我们将递归级别定义为m
,则每个级别的函数调用次数为
每次我们递归时,我们也将数组的大小减半,因此每个函数调用的工作量是
在每个递归级别,总共完成的工作是:
实际上4^m
与(2^m)^2
相同:
因此,工作量可以写成n^2
:
有log n
个递归级别。
因此总工作量为O(n^2 * log n)
,即,因为有4次递归调用。
如果只有2个递归调用,则每个级别的工作量将为
我们不能很好地减少(但如果我的数学是正确的,那么结果是O(n^2)
。)