【发布时间】:2019-03-02 09:00:49
【问题描述】:
在之前的一篇cs考试介绍中有一个问题:计算函数f1的空间和时间复杂度作为n的函数,假设malloc(n)的时间复杂度是O(1),它的空间复杂度为 O(n)。
int f1(int n) {
if(n < 3)
return 1;
int* arr = (int*) malloc(sizeof(int) * n);
f1(f1(n – 3));
free(arr);
return n;
}
官方的解法是:时间复杂度:O(2^(n/3)),空间复杂度:O(n^2)
我试图解决它,但我不知道如何解决,直到我在笔记本上看到一条注释:既然函数返回 n,那么我们可以将 f(f(n-3)) 视为 f(n-3 )+f(n-3) 或 2f(n-3)。在这种情况下,问题变得与这个问题非常相似:Space complexity of recursive function
我试着用这种方法解决它,我得到了正确的答案。
对于时间复杂度:
T(n)=2T(n-3)+1 , T(0)=1
T(n-3)=2T(n-3*2)+1
T(n)=2*2T(n-3*2)+2+1
T(n-3*2)=2T(n-3*3)+1
T(n)=2*2*2T(n-3*3)+2*2+2+1
...
T(n)=(2^k)T(n-3*k)+2^(k-1)+...+2^2+2+1
n-3*k=0
k=n/3
===> 2^(n/3)+...+2^2+2+1=2^(n/3)[1+(1/2)+(1/2^2) +...]=2^(n/3)*常数
因此我得到了 O(2^(n/3))
对于空间复杂度:树的深度是 n/3,每次我们做 malloc 所以我们得到 (n/3)^2 因此 O(n^2)。
我的问题:
- 为什么我们可以将 f1(f1(n – 3)) 视为 f1(n-3)+f1(n-3) 或 2f1(n-3)?
- 如果函数没有返回n而是改变了它,例如:return n/3而不是return n,那我们该如何解决呢?我们是否将其视为 2f1((n-3)/3)?
- 如果我们不能总是将 f1(f1(n – 3)) 视为 f1(n-3)+f1(n-3) 或 2f1(n-3) 那么我们如何绘制递归树和我们如何使用归纳法 T(n) 编写和求解?
【问题讨论】:
标签: recursion time-complexity big-o space-complexity