Pow(x, n)(Medium)
实现 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
提示:
-100.0 < x < 100.0
-231 <= n <= 231-1
n 是一个整数
要么 x 不为零,要么 n > 0 。
-104 <= xn <= 104
Related Topics
递归
数学
思路分析
最开始我是根据提示使用递归的方法来完成这个问题,然后在进行案例测试的过程中,发现如果使用暴力地使用逐个相乘的房法去递归的话,在幂次特别大的情况下,递归会导致程序的调用堆栈超出了它的限制。这通常发生在递归调用中没有适当的终止条件或者有太深的递归层次时。所以就要想一想如何去优化这个递归过程,也就是有没有更优的方法来完成乘幂的操作。
这里要使用的叫做快速幂算法,就是说,幂运算的过程可以看成是多个更小的幂运算过程相乘,那么怎么进行分割呢?这里就可以考虑对于幂次进行二进制的转换,因为二进制的的每一位的换算就是根据所在位置对2进行幂运算,所以对幂次进行二进制的转换,只要是1的位置就把该位置代表的次数与结果相乘。这样可以大大减少递归的层数。
这样说有点抽象这里我来举个例子:
代码实现
class Solution {
public double myPow(double x, int n) {
double res = 1.0;
// 处理特殊情况
if(x == 0)return 0;
if(x == 1 || n == 0)return 1;
if(x == -1)return n % 2 == 1 ? -1 : 1;
// n为负数的情况
if(n < 0){
// n为最小整数,直接取反数值越界,等于Integer.MAX_VALUE + 1
if(n == Integer.MIN_VALUE){
return 1 / (newPow(x, Integer.MAX_VALUE, res) * x);
}
// 否则 x^n = 1/(x^(-n))
return 1 / newPow(x, -n, res);
}
// n为正数的情况
return newPow(x, n, res);
}
private double newPow(double x, int n, double result){
if (n <= 0){
return result;
}
if((n & 1) == 1){
result *= x; // n的二进制当前位为1,则累乘当前的x
}
x *= x; // x的2的指数次方幂
n >>= 1;
return newPow(x, n, result);// n右移一位
}
}