在O(log n)中计算x ^ y

时间:2012-04-17 16:30:55

标签: c algorithm big-o

面试问题:

  

在O(log n)中计算x ^ y

有不同的答案,如“使用印度力量算法”或

double power(double x, int y) 
{
    if(y == 0) return 1;

    double d = power(x, y/2);

    if(y%2 == 0) return d*d;
    else return x*d*d;
}
  1. 这是一个正确答案吗?

  2. 有没有更好的方法来编写这个问题的代码?

5 个答案:

答案 0 :(得分:8)

这称为Exponentiation by Squaring。就实施而言,这是一个品味问题。你的递归实现是好的,但非递归实现(来自上面的链接)对于那些不喜欢递归或者错误地认为它在某种程度上“浪费”或“慢”的人来说可能看起来更清晰。

答案 1 :(得分:2)

有关基本数学运算的问题以及有关计算复杂性的问题,维基百科通常会迅速回答。

ExponentiationEfficient computation of integral powers

  

通常,通过使用求平方或(更一般地)加法链取幂,可以将计算bn所需的乘法运算的数量减少到Θ(log n)。找到最小乘法序列(指数的最小长度加法链)是一个难以解决的问题,目前还没有有效的算法(参见子集求和问题),但是可以使用许多合理有效的启发式算法。

答案 2 :(得分:1)

让我们分析一下:

power被调用(通过递归),原始y可被2整除(这是最大数字k,因此2^k < y) 。这意味着计算的数量大致为k=log_2(2^k)=log_2(y)~=log(y),因此这是一个正确的答案。

“更好的方式”的答案取决于什么算“更好”

答案 3 :(得分:1)

这是做到这一点的方法:

让我们说你想要2 ^ 1024,那将需要......等待...... 11次乘法

你这样做

2*2 = 2^2
2^2 * 2^2 = 2^4
2^4 * 2^4 = 2^8
2^8 * 2^8 = 2^16
....
2^512 * 2^512 = 2^1024

所以基本上,你只需要在基数2中编写指数并得到所有相关的乘法

答案 4 :(得分:-2)

速度要快得多:%是一项非常昂贵的操作,用一个按位操作取而代之的是一个巨大的节省;同时将y/2替换为y>>1

double power(double x, int y) {
    if(y == 0) return 1;

    double d = power(x, y>>1);

    if((y&1) == 0) return d*d;
    else return x*d*d;
}