[leetCode]剑指 Offer 16. 数值的整数次方
解法一
此题需要关注边界问题:
- 当为0,n<0 时会出现 0为底的情况
- 对 int 型数据 -2147483648 求绝对值,结果仍为 -2147483648:参考
考虑到这两点后可以很快的用for循环实现o(n)的算法,但是为了降低时间复杂度可以使用递归或快速幂,以下代码使用递归求解。假设需要求一个数字的32次方,则需要知道其16次方。而16次方是8次方的平方,以此类推需要做5次乘法:
class Solution {
public double myPow(double x, int n) {
if(x == 0.0 && n < 0.0) return 0.0;
long absExponent = n;
if(absExponent < 0) absExponent = -(long)n;
if(n < 0) return 1d / powWithAbsExponent(x,absExponent);
return powWithAbsExponent(x,absExponent);
}
private double powWithAbsExponent(double base, long absExponent ){
if(absExponent == 0)
return 1;
if(absExponent == 1)
return base;
double result = powWithAbsExponent(base, absExponent >> 1);
result *= result;
if((absExponent & 1) == 1)
result *= base;
return result;
}
}
解法二 快速幂
把n转换为二进制,对x使用n的二进制进行展开即可求解:参考
class Solution {
public double myPow(double x, int n) {
if(x == 0 && n < 0) return 0.0;
long absExponent = (long)n;
if(absExponent < 0) absExponent = -(long)n;//先强转防止溢出
if(n < 0) return 1d / powWithAbsExponent(x,absExponent);
return powWithAbsExponent(x,absExponent);
}
private double powWithAbsExponent(double base, long absExponent ){//实现快速幂
double res = 1.0;
while(absExponent > 0){
if((absExponent & 1) == 1){
res *= base;
}
absExponent = absExponent >> 1;
base *= base;
}
return res;
}
}