【发布时间】:2022-01-26 06:18:27
【问题描述】:
以下函数的时间复杂度是多少?
int f = (int n) => {
if (n === 1) {
return 1;
}
for (let i = 0; i < n; i++) {
console.log(i);
}
return f(n-1) + f(n-1)
}
这就是 递归树 的样子,i 表示深度:
f(4) // i = 0
/ \
/ \
/ \
/ \
/ \
f(3) f(3) // i = 1
/ \ / \
/ \ / \
f(2) f(2) f(2) f(2) // i = 2
/ \ / \ / \ / \
f(1) f(1) f(1) f(1) f(1) f(1) f(1) f(1) // i = 3
如果函数内部没有循环,时间复杂度将是O(2^n)。但是现在有一个循环:
在每个深度,进行的函数调用次数为2 ^ i,并且在每个函数调用n - i 中,迭代都在循环中完成,因此在每个级别上都进行了(2 ^ i) * (n - i) 操作。因此,时间复杂度可以计算为:
T(n) = [(2 ^ 0) * (n - 0)] + [(2 ^ 1) * (n - 1)] + [(2 ^ 2) * (n - 2)] + ... + [(2 ^ (n - 1)) * (n - (n - 1))]
那么我说得对吗?最终的时间复杂度可能是多少?
【问题讨论】:
-
您确定提供的代码是 C++ 而不是 JavaScript?
-
每个函数调用都需要线性时间,所以大概是 2^n 乘以 n。
-
@kiner_shah:可能不会。
-
你有正确的时间复杂度方程。您只需将其插入 wolfram alpha 即可获得答案:wolframalpha.com/input/?i=sum%282%5Ei%28n-i%29%2C+i%3D0..n%29。手动计算,
sum(i*2^i)可以计算为x * d/dx(sum(x^i)在 x=2 处求值。您需要注意我在此评论中省略的总和的限制。 -
递归关系的老派方法是猜测答案然后证明它。当您必须猜测时,您可以使用 wolfram alpha 替换该部分(这通常需要解决您拥有的特定类型的方程的经验,或者努力绘制数字并以这种方式了解答案)。完成后,您仍然拥有有效的证明!
标签: algorithm loops recursion time-complexity