考虑以下C函数:
double foo (int n) {
int i;
double sum;
if (n == 0) return 1.0;
else {
sum = 0.0;
for (i = 0; i < n; i++)
sum + = foo (i);
return sum;
}
}
上述功能的空间复杂性是
1) O(1)
2) O(n)
3) O(n!)
4) O(n^n)
在上述问题中,据我所知,答案应该是(2)但答案是(3)选项。虽然它是递归函数但堆栈永远不会超过O(n)堆栈深度。任何人都可以解释我为什么这个答案(3)我在哪里思考错了?
答案 0 :(得分:3)
如果您需要时间复杂度,那么它肯定不会像O(N!)
那么多,但会比O(2^N)
更少。
证明: -
T(N) = T(N-1) + T(N-2) + T(N-3) + T(N-4)........T(1)
此外,通过以上公式
T(N-1) = T(N-2) + T(N-3)...... T(1)
因此T(N) = T(N-1) + T(N-1) = 2*T(N-1)
上面解决了T(N) = O(2^N)
然而,如果您需要空间复杂度,那么对于递归函数空间复杂度是通过它在某个时刻占用的最大堆栈空间量来计算的,并且在这种情况下不能超过O(N)
但无论如何答案不是O(N!)
,因为很多计算都没有完成,所以堆栈如何占用那么多空间。
注意: - 尝试运行n = 20
的函数,如果它不会导致内存溢出,那么文本中给出的答案将为20!它比任何内存都大,但我认为它会在O(2^20)
时间内运行而不会出现任何堆栈溢出。
答案 1 :(得分:1)
这样想:
计算 foo(n)。程序必须计算:foo(0)+ foo(1)+ foo(2)... foo(n-1):
同样适用于foo(n-1)。程序必须递归计算:foo(0)+ foo(1)+ ... foo(n-2)。
基本上你会有O(foo(n))= n! +(n-1)! +(n-2)! + ... 1! = O(n!)。
希望这很清楚。
答案 2 :(得分:1)
空间复杂度为O(N)。在任何给定时间,使用的空间限于:
N*sizeof_function_call_which_is_a_constant
。