实现 pow(x, n) ,即计算 x
的整数 n
次幂函数(即,xn
)。
示例 1:
输入:x = 2.00000, n = 10 输出:1024.00000
示例 2:
输入:x = 2.10000, n = 3 输出:9.26100
示例 3:
输入:x = 2.00000, n = -2 输出:0.25000 解释:2-2 = 1/22 = 1/4 = 0.25
方法
「快速幂算法」的本质是分治算法。举个例子,如果我们要计算,我们可以按照:
的顺序,从开始,每次直接把上一次的结果进行平方,计算次就可以得到的值,而不需要对乘次。
再举一个例子,如果我们要计算,我们可以按照:
的顺序,在,,这些步骤中,我们直接把上一次的结果进行平方,而在,,这些步骤中,我们把上一次的结果进行平方后,还要额外乘一个。
直接从左到右进行推导看上去很困难,因为在每一步中,我们不知道在将上一次的结果平方之后,还需不需要额外乘。但如果我们从右往左看,分治的思想就十分明显了:
当我们要计算时,我们可以先递归地计算出,其中表示对进行下取整;
根据递归计算的结果,如果为偶数,那么;如果为奇数,那么;
递归的边界为,任意数的次方均为。
由于每次递归都会使得指数减少一半,因此递归的层数为,算法可以在很快的时间内得到结果。
代码
class Solution {
public:
double quickMul(double x, long long N) {
if (N == 0) {
return 1.0;
}
double y = quickMul(x, N / 2);
return N % 2 == 0 ? y * y : y * y * x;
}
double myPow(double x, int n) {
long long N = n;
return N >= 0 ? quickMul(x, N) : 1.0 / quickMul(x, -N);
}
};
复杂度分析
时间复杂度:,即为递归的层数。
空间复杂度:,即为递归的层数。这是由于递归的函数调用会使用栈空间。