实现double Pow(double x,int n)—-x的n次幂!
题目解析:
这道题目看起来很简单,笨方法,可以一次一次的去乘,也可以折半相乘!看似简单,但中间碰到了不小的问题。
在运行过程中,出现了-2147483648超时。为什么?
来看下面代码:
class Solution{
public:
double pow(double x,int n){
if(n == 0)
return 1.0;
if(n == 1)
return x;
if(n < 0){
//方案一
return 1.0/pow(x,-n);
//方案二
n = -n;
double half = pow(x,n/2); //只计算一次,效率更高!
if(n%2 == 0)
return 1.0/(half*half);
return 1.0/(x*half*half);
}
double half = pow(x,n/2); //只计算一次,效率更高!
if(n%2 == 0)
return half*half;
return x*half*half;
}
};
方案一时会报错,但方案二却没有?
差别在哪里?在于整数正负数范围不对称引起的错误,-2147483648再取负数,还是其自身,那么方案一就会无限死循环下去,深层次的n还是小于0。但方案二却没有,因为传递的时候已经确保了n/2不再是最大的负数,会跳出死循环。
网上还有另外一种方法,也没有出错,来看一下:
class Solution {
public:
double powPositive(double x, int n){
if(n == 0) return 1;
if(n == 1) return x;
double tmp;
if(n%2 == 0){
tmp = powPositive(x, n/2);
return tmp*tmp;
}
tmp = powPositive(x, n/2);
return tmp*tmp*x;
}
double pow(double x, int n) {
// Start typing your C/C++ solution below
// DO NOT write int main() function
if(n >= 0) return powPositive(x,n);
return 1/powPositive(x,-n);
}
};
他也是直接将-n传入。但不是本身的函数,而是子函数,况且子函数当中也不再对负数n进行判断。最后能通过测试。
但更完美的方法还是《【剑指offer】面试题11:数值的整数次方》这个里面的方案,已经把0的情况也考虑进去了,并且对负数进行了的彻底的转化unsigned int ,同时调用子函数去求解。
这道题还是很值得仔细去研究的。