我正在尝试计算递归算法的时间复杂度,我想我差不多了。这是我一直在看的伪代码:
long pow( long x, int n ) {
if (n == 0)
return 1;
if (n == 1)
return x;
if(isEven(n))
return pow(x, n / 2 ) * pow(x, n / 2);
else
return x * pow(x * x, n / 2);
}
isEven仅仅确定传递给它的整数是否是偶数,并且就本例而言,它是在恒定时间内运行。
因此,如果n = 0或n = 1,它运行它具有恒定时间操作,如下所示: f(n)= C0。 但是,当n> 1,它应该像这样运作: 当n为偶数时,f(n)= f(n-1)+ f(n-1)+ C1,当n为奇数时,f(n)= f(n-1)+ 1,正确吗?或者应该是:f(n)= f(n / 2)+ f(n / 2)+当n是偶数时的C1和当n是奇数时f(n)= f(n / 2)+ 1?
我一直在看很多例子。 Here是我发现非常有帮助的。我的问题源于当n是偶数时有两个递归调用 - 我不完全确定在这里做什么。如果有人能指出我正确的方向,我真的很感激。
答案 0 :(得分:3)
看看Master Theorem。您可以将此视为“分而治之”算法。
最终结果是,在两个递归调用到位的情况下,最终会出现最坏情况的O(n)运行时。例如。 pow(x,4)将pow(x,2)称为两次,将pow(x,1)称为四次;一般来说,2的幂将导致n * 2-1次呼叫。
另请注意,只需调用pow(x,n / 2)一次并将结果平方化为该分支,算法就会变为O(log n)。
答案 1 :(得分:0)
让我们定义f(m),因为它给出了大小为m的问题的操作次数。 “问题”当然是取幂(pow),如x^n
或pow(x,n)
。如果我更改x,long pow( long x, int n ) {
函数不需要做更多或更少的工作。因此,问题取幂的大小不依赖于x。但它确实取决于n。假设2 ^ 4的大小为4,3 ^ 120的大小为120.(如果您看到2^4=2*2*2*2
和3^120=3*3*3*3*..*3
,则有意义)问题大小因此等于n
,第二个参数。如果你愿意,我们可以说问题的大小是2 * log(n),但这很愚蠢。
现在我们有f(m)是计算任何x的pow(x,m)
的操作数。因为pow(x,m)
正是尺寸为m的问题。 因此,如果我们有pow(x,y)
,那么根据定义,操作数量为f(y)
。例如,pow(3,3*m/2)
有f(3*m/2)
次操作。< / p>
最后,让我们计算一下操作
long pow( long x, int n ) {
if (n == 0) //1
return 1;
if (n == 1) //1
return x;
if(isEven(n)) //1
return pow(x, n / 2 ) * //that is f(n/2), y=n / 2
pow(x, n / 2); //also f(n/2)
else
return x * pow(x * x, n / 2); //1+1+f(n/2)
}
将它们放在一起:f(n) = 2*f(n/2) + c1
(n偶数)和f(n) = f(n/2) + c2
(n奇数)。如果你只对最糟糕的情况感兴趣,那么请注意奇数情况下的工作量较少。因此,f(n)在偶数情况下界定:f(n) <= 2*f(n/2)+c
。