如何解决:T(n)= T(n / 2)+ T(n / 4)+ T(n / 8)+(n)

时间:2011-04-11 22:23:09

标签: algorithm recursion recurrence

我知道如何对只调用一次的算法进行递归关系,但我不确定如何在一次出现时多次调用自身。

例如:

T(n) = T(n/2) + T(n/4) + T(n/8) + (n)

5 个答案:

答案 0 :(得分:6)

使用递归树。请参阅CLRS“算法简介”中的递归树的最后一个示例。

T(n)= T(n / 2)+ T(n / 4)+ T(n / 8)+ n。根将是n(成本)&分为3次递归。因此递归树如下所示:

T(n)= n = n         T(n / 2)T(n / 4)T(n / 8)(n / 2)(n / 4)(n / 8)                             T(n / 4)T(n / 8)T(n / 16)T(n / 8)T(n / 16)T(n / 32)T(n / 16)T(n / 32)T( N / 64)

                                             n---------------------------------> n      

                             (n/2)         (n/4)           (n/8)--------------> (7/8)n

                         n/4 n/8 n/16  n/8 n/16 n/32  n/16 n/32 n/64)--------> (49/64)n
                                            ...         

最长路径:最左边的分支= n - > n / 2 - > n / 4 - > ... - > 1

最短分支:最右边的分支= n - > n / 8 - > n-> 64-> ... - > 1

叶子数(l):3 ^ log_8(n)< l< 3 ^ log_2(n)=> n ^ 0.5< l< N R个1.585

查看树 - 树木已满的log_8(n)级别,然后当我们下降时,更多&没有更多的内部节点。通过这个理论,我们可以给出界限,

T(n)= Big-Oh(求和j = 0至log_2(n)-1(7/8)^ j n)= ... => T(n)= O(n)。 T(n)= Big-Omega(求和j = 0至log_8(n)-1(7/8)^ j n)= ... => T(n)= Big-Omega(n)。

因此,T(n)= Theta(n)。

这里的要点是: T(n / 2)路径的长度最长......

这绝不是一个完整的三元树...高度= n&的基数2叶子数量必须少于n ...

希望,很可能这样你可以解决问题。

答案 1 :(得分:3)

有两种方法可以解决这个问题。一个是展开递归并发现可能需要创造性并且可能非常难的相似性。另一种方法是使用Akra-Bazzi method

在这种情况下g(x) = na1 = a2 = a3 = 1b1 = 1/2b2 = 1/4b3 = 1/8。求解方程式

enter image description here

1/2^p + 1/4^p + 1/8^p = 1获得p = 0.87915。求解积分后,您将获得enter image description here,这意味着复杂性为:O(n)

答案 2 :(得分:0)

正如CLRS所说,可以通过数学归纳法将T(n)替换为cn。此归纳假设适用于n以下的数字。如上所述,我们需要证明参数值是n。因此,如下: 假设:T(n) <= cn代表n以下的数字; 结论:

T(n) = T(n/2) + T(n/4) + T(n/8) + n
    <= c/2*n + c/4*n + c/8*n + n
     = (7/8*c + 1) * n
    <= cn (when c >= 8)

仅此而已。

答案 3 :(得分:0)

请参见图片以获取更好的解释-

enter image description here

树的高度:我们采用log(n)(基数2)是因为n / 2使树的长度比n / 4和n / 8更长。我们的GP系列将一直持续到k = logn(base)。

答案 4 :(得分:-1)

就像编码Fibonacci序列(艰难的方式)一样,你只需输入以下内容:

long fib(long n){
 if(n <= 1) return n; 
 else return fib(n-1) + fib(n-2);
}     

或者,更好的是,使用全局变量对其进行记忆以使其更快。再次,使用Fibonacci序列:

static ArrayList<Long>fib_global = new ArrayList(1000); 
  //delcare a global variable that can be appended to
long fib(long n){
   if(n >= fib_global.length)fib_global.add(fib(n-1) + fib(n-2));
   return fib_global.get(n);
}

代码一次只能执行其中一个调用,并且很可能是按照从左到右的顺序执行,这使得您只需要不必担心次数你需要打电话。