面试题:
在 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;
}
这是一个正确的答案吗?
有没有更好的方法来为这个问题编写代码?
这称为平方求幂。就实施而言,这是一个品味问题。您的递归实现很好,但是对于不喜欢递归或错误地认为它在某种程度上“浪费”或“缓慢”的人来说,非递归实现(来自上面的链接)可能看起来更干净一些。
我们来分析一下:
power
被调用(通过递归)的次数与原始y
可被 2 整除的次数一样多(即最大数,k
,使得2^k < y
)。这意味着计算的次数大致为k=log_2(2^k)=log_2(y)~=log(y)
,所以它是一个正确的答案。
“更好的方式”的答案取决于什么才是“更好”
这是执行此操作的方法:
假设你想要 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 为底写你的指数并得到所有相关的乘法
这里要快得多:%
是一个非常昂贵的操作,用按位操作代替它是一个巨大的节省;也替换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;
}