面试问题:
在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;
}
这是一个正确答案吗?
有没有更好的方法来编写这个问题的代码?
答案 0 :(得分:8)
这称为Exponentiation by Squaring。就实施而言,这是一个品味问题。你的递归实现是好的,但非递归实现(来自上面的链接)对于那些不喜欢递归或者错误地认为它在某种程度上“浪费”或“慢”的人来说可能看起来更清晰。
答案 1 :(得分:2)
有关基本数学运算的问题以及有关计算复杂性的问题,维基百科通常会迅速回答。
Exponentiation:Efficient 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;
}