算法的递归关系

时间:2018-09-24 13:16:53

标签: c algorithm recursion recurrence

我已经给出了以下算法,必须找到递归关系。

int Recursive(int n)
{
   if(n<=1)
     return n;
   sum=0;
   for(int j=0;j<n;j++)
      sum++;
   return Recursive(n/2) + Recursive(n/2) + sum;
}

对于上述算法,我已经获得了递归关系

T(n) = 2 T(n/2) + constant

但是我不确定这个递归关系的常数部分,因为我们在算法中有sum。需要说明的是,sum是一个全局变量-缺少声明不是 错字。

有人可以帮助我获得正确的复发关系吗?谢谢。

2 个答案:

答案 0 :(得分:0)

  

我不确定该递归关系的恒定部分

由于循环后sum等于n,所以没有常数部分。这给出了:

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

因此,如果sum为全局变量T(n) = 2T(n/2)+C(Constant),并且sum为局部变量T(n) = 2T(n/2)+n。我说得对吗?

不,正如mch写道:

  

似乎sum是一个全局变量……在这种情况下,将不确定是否首先评估sumRecursive(n/2)之一。

这意味着T(n) = 2T(n/2)+nT(n) = 2T(n/2)+n/2未指定;在任何情况下都不存在恒定的部分。

答案 1 :(得分:0)

此答案中的假设:

  • sum是全局声明的-因为显然缺失的声明不是您输入的错字。
  • 问题要求返回值,而不是时间复杂度。
  • return语句中的表达式按其出现顺序求值; C标准不能保证这一点,因此答案在技术上是不确定的。

请注意,由于每个调用都会执行以下操作:

  • 返回其自变量(如果为n <= 1
  • sum的值重置为0

...从某种意义上说,函数的返回值将仅取决于其参数,从而保证“关闭”函数。因此,

  

Recursive(n / 2)的两个单独的调用可以组合为一个调用,而不会影响返回值:return 2 * Recursive(n / 2) + sum;

从现在开始,假定已将此修改应用于原始代码;这有助于澄清程序的流程,因为现在只有一个执行路径(而不是由两个调用创建的分支)。


现在是关键部分。对Recursive(n / 2)的调用将在函数返回之前覆盖sum的值{em},从而撤消前一个for循环所做的工作。这种覆盖行为会在递归层次结构中持续下去,直到终止条件n <= 1被击中(直到返回n为止)。因此,

  

sum只有一个值会影响最终的返回值,该值由倒数第二个调用Recursive后的值给出


由于被整数除法截断,当执行倒数第二次调用时,n始终为 2 3 (两者都是满足n / 2 = 1);因此,这些也是sum的可能最终值。

n的哪些值分别给sum = 2sum = 3?考虑n的二进制表示是说明性的。

整数除以2等于将位模式“右”移位1(或根据字节序为“左”),并丢弃最低有效位。因此,sum的最终值仅取决于n 2 个最高有效位:

 initial bit-pattern  >>  penultimate call
 -----------------------------------------
 ...000 10 xxx...         ...0000 10 = 2       
 ...000 11 xxx...         ...0000 11 = 3

 xxx: discarded bits

n的位模式具有floor(log2(n)) + 1个有效位; sum的最终值因此可以紧凑地表示为:

S(n) = 2 + second_most_significant_bit(n)

sum被添加到返回值多少次?对Recursive递归呼叫次数(即呼叫总数减去一个,包括初始呼叫,但不包括最终呼叫)。由floor(log2(n))给出:

enter image description here

请注意,如果最初为1,则最终调用的返回值将始终为n >= 1。因此,Recursive的最终返回值由下式给出:

  

enter image description here


测试C代码进行确认:

// override the library definition of log2 to use integers only
int log2(int n) {
   int b = 0;
   while ((n >>= 1) != 0)
      b++;
   return b;
}

// get i-th bit from bit pattern of n
int get_bit(int n, int i) {
   return (n >> (i - 1)) & 1;
}

// calculating return value of Recursive using equation above
int Value(int n) {
   int l2n = log2(n);    // floor(log2(n))
   int p2l = 1 << l2n;   // 2^(floor(log2(n)))
   return p2l + (p2l - 1) * (2 + get_bit(n, l2n));
}

结果:

n        | Recursive    Value
-------------------------------
2        |  4           4
3        |  5           5
4 - 5    |  10          10
6 - 7    |  13          13
8 - 11   |  22          22
12 - 15  |  29          29
16 - 23  |  46          46
24 - 31  |  61          61
32 - 47  |  94          94
48 - 63  |  125         125
64 - 95  |  190         190