时间复杂度递归程序

时间:2017-08-17 11:22:05

标签: time-complexity

我无法弄清楚以下代码片段的时间复杂性:

void  f( int N ){
   sum ++;
   if ( N   > 1){
      f( N /2);
      f( N /2);
   }

这是给我带来问题的双重迭代。

我知道(或认为)

的时间复杂性
void  f( int N ){
   sum ++;
   if ( N   > 1){
      f( N /2);
   }

是~log2(N),但不知道如何处理其他代码。

4 个答案:

答案 0 :(得分:3)

您在(N/2)上调用了两次递归。让我们写下公式:

T(n) = 2*(N/2) + 1

使用master theorem,我们会遇到第一种情况:

  • a = 2
  • f = O(1)
  • B = 2
T(n) = Θ(n)

我们还发现 T(n)= 2 * T(n / 2)+ 1 here,这表明它受O(n)

的限制

答案 1 :(得分:3)

解决这个问题的好方法是:

1。查找重现关系

对于f的每次通话,我们都有时间复杂度T(N)。每个电话都包含:

  • 一定量的工作Csum++,比较N > 1,递归调用开销等。
  • f的2次递归调用,每次调用时间复杂度为T(N / 2)

因此递归关系T(N) = 2T(N/2) + C给出。

2。通过检查找到解决方案

如果我们反复将T(N)替换为自己,我们可以看到一种新兴模式:

enter image description here

求和的上限是m?由于停止条件为N > 1,因此在重复替换之后,要求将是

enter image description here

因此求和等于(放下舍入和常量C,因为它只是乘法):

enter image description here

3。通过归纳证明

  • 基本步骤:测试总和结果是否正确N的最低可能值,即2:

    enter image description here

    结果是一致的。

  • 重复步骤:确认如果N / 2的总和是正确的,N也是正确的:

    enter image description here

    这正是我们原来的复发关系。

因此,通过归纳,求​​和结果是正确的,T(N)确实是Ө(N)

4。数值测试:

如果需要,我们可以编写代码来确认我们的结果:

function T(n) {
  return n > 1 ? 2 * T(floor(n/2)) + 1 : 1;
}

结果:

N           T(N)
-------------------------
2           3
4           7
8           15
16          31
32          63
64          127
128         255
256         511
512         1023
1024        2047
2048        4095
4096        8191
8192        16383
16384       32767
32768       65535
65536       131071
131072      262143
262144      524287
524288      1048575
1048576     2097151
2097152     4194303
4194304     8388607
8388608     16777215
16777216    33554431
33554432    67108863
67108864    134217727
134217728   268435455
268435456   536870911
536870912   1073741823
1073741824  2147483647

图表:

enter image description here

答案 2 :(得分:2)

让我们尝试追踪它:

设N为8

1 + f(4)+ f(4)
=> 1 + 2 + f(2)+ f(2)+ f(2)+ f(2)
=> 1 + 6 + f(1)+ f(1)+ f(1)+ f(1)+ f(1)+ f(1)+ f(1)+ f(1)

当n = 8时; work = 15

设N为4

1 + f(2)+ f(2)
=> 1 + 2 + f(1)+ f(1)+ f(1)+ f(1)

当n = 4时; work = 7

设N为2

1 + f(1)+ f(1)

当n = 2时; work = 3;

设N为1

1

当n = 1时; work = 1

所以一眼就看出工作模式似乎 2n - 1

我们仍然需要证明它!

从算法中,递归关系是:

W(1)= 1
W(N)= 1 + 2 * W(N / 2)

通过归纳证明

基本案例:
W(1)= 2(1) - 1 = 1 根据需要

递归案例:
假设W(N / 2)= 2(n / 2) - 1 = n - 1

W(N)= 1 + 2 *(N / 2)
应用归纳法......
W(N)= 1 + 2(n - 1)= 1 + 2n - 2 = 2n - 1 根据需要

因此,复杂性 O(2n - 1)因为 O是反身的

=> O(max {2n,-1})总和规则
=>的 O(2N)

=>由于缩放规则

O(n)

答案 3 :(得分:0)

此代码与二进制树遍历

非常相似
void  f( int N ){
   sum ++;
   if ( N   > 1){
      f( N /2);  //like Traverse left subtree
      f( N /2);  //like Traverse right subtree
   }

基本遍历每个节点一次,时间复杂度O(N)

                    n/8
             n/4   --------- 
                    n/8
      n/2   ------------------    

                    n/8
             n/4  ---------
                    n/8

n -------------------------------
                    n/8
             n/4    --------- 
                    n/8
      n/2   ----------------

                    n/8
             n/4   ---------
                    n/8

这一直持续到传递的值变为1或0。