以下功能的空间复杂性是什么?如何?

时间:2016-02-05 00:21:23

标签: recursion big-o space-complexity

考虑使用递归函数。

int f(int n){
   if(n<=0) return 1; return f(n-1)+f(n-1);
}

据说尽管有2^N(2次供电至N次)通话,但在指定时间只有N次通话。有人可以解释一下吗?

2 个答案:

答案 0 :(得分:2)

不确定。复杂性部分位于 else 部分:

return f(n-1)+f(n-1)

这会在 n 的每次通话中以 n-1 产生两个电话。但是,请注意评估顺序:

call f(n-1) ... left side
save the value as temp1
call f(n-1) ... right side
add the value to temp1
return that value

整个左侧调用树必须在右侧调用树开始之前完成 - 这发生在每个深度级别。对于 n 的每个值,在任何时间点都只有一个呼叫处于活动状态。例如,f(2)给出了这样一个序列:

call f(2)
n isn't <= 0 ...
    call f(1) ... left
    n isn't <= 0 ...
        call f(0) ... left | left
        n <= 0; return 1
        save the 1
        call f(0) ... left | right
        n <=0; return 1
        add the 1 to the temp value;
        return 2
    save the 2
    call f(1) ... right
        call f(0) ... left | left
        n <= 0; return 1
        save the 1
        call f(0) ... left | right
        n <=0; return 1
        add the 1 to the temp value;
        return 2
    add this 2 to the temp value, making 4
    return the 4
done ...

在每个点上,只有n + 1个调用处于活动状态(参见缩进级别),尽管我们最终会执行2 ^(n + 1)-1次调用。我们关闭一个(n + 1而不是n)因为我们终止于0而不是1。

这样清楚了吗?

答案 1 :(得分:1)

对于每个nf(n-1)被调用两次。因此,如果您在根处绘制一个n的树并为每个f(n-1)调用添加一个分支,依此类推,您将看到您有一个高度为n的完整二叉树,其中有2 ^ n个节点(总呼叫数)。 但重要的是要注意,如果没有先完成第一次调用并返回结果,则无法启动对f(n-1)的第二次调用。对于f(n-2)内的f(n-1)调用,......递增递归,<。p>

最糟糕的情况(我假设这就是你要找的东西),当你的函数调用集到达f(0)并且你在调用树的一个叶子时发生。调用堆栈中的内容是从f(n-1)f(n-2),...,f(1)f(0)开始的一组函数调用。因此,在每个时间点,堆栈中最多只有O(n)函数。 (它等于调用树的高度)。