考虑使用递归函数。
int f(int n){
if(n<=0) return 1; return f(n-1)+f(n-1);
}
据说尽管有2^N
(2次供电至N次)通话,但在指定时间只有N
次通话。有人可以解释一下吗?
答案 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)
对于每个n
,f(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)函数。 (它等于调用树的高度)。