Question
Implement pow(x, n).


本题难度Medium。

【复杂度】
时间 O(log(N)) 空间 O(1)

【思路】
分治法。

【代码】

public class Solution {
public double myPow(double x, int n) {
//require
if(n==0)
return 1.0;
//invariant
if(n<0)
return 1.0/pow(x,-(long)n);
else
return pow(x,n);
}

private double pow(double x,long n){
//bound
if(n==1)
return x;
double v=pow(x,n/2);
if(n%2==1)
return v*v*x;
else
return v*v;
}
}

【注意】
你觉得代码可以这样写吗:

public class Solution {
public double myPow(double x, int n) {
//require
if(n==0)
return 1.0;
//invariant
if(n<0)
return 1.0/pow(x,-n); //wrong
else
return pow(x,n);
}

private double pow(double x,int n){
//bound
if(n==1)
return x;
double v=pow(x,n/2);
if(n%2==1)
return v*v*x;
else
return v*v;
}
}

这么写,会在n=INT_MIN时出错!

当​​n=INT_MIN​​​也就是​​-10^31​​​时,第8行的​​-n​​​得到的结果仍然是​​INT_MIN​​:

如果 INT_MIN=0x80000000  也就是-10^31
要注意!!!-INT_MIN 不是等于 10^31
要严格按照计算机的计算负数的过程,先取反,再加1
0x80000000 -取反-> 0x7FFFFFFF -加1-> 0x80000000
结果是:
-INT_MIN=INT_MIN

也就是说pow函数的参数n输入的是​​INT_MIN​​​,这样就必然出错(它是负数,而pow函数不能处理负数)。要避免它就要在第8行将​​n​​​转换为​​long​​​。不过别写错了,不是​​(long)-n​​​,这样得到的结果是​​-10^31​​​;应该写成​​-(long)n​​​,得到的结果是​​10^31​​。

【附】
也有的答案是这样的:

public class Solution {
public double myPow(double x, int n) {
//require
if(n==0)
return 1.0;
//invariant
if(n<0)
return 1.0/pow(x,-n);
else
return pow(x,n);
}

private double pow(double x,int n){
//bound
if(n==0)
return 1;
double v=pow(x,n/2);
if(n%2==0)
return v*v;
else
return v*v*x;
}
}

为什么它没有把n转换为long呢?
1、它的pow函数可以处理负数
2、​​​-INT_MIN=INT_MIN​​​保证了数值没有变化。如果​​-INT_MIN​​​ 不等于​​INT_MIN​​,那它就错了。

你把第8行​​return 1.0/pow(x,-n);​​​改为​​return 1.0/pow(x,n);​​照样可以。实际上更为好的代码就是这样的:

public class Solution {
public double myPow(double x, int n) {
//require
if(n==0)
return 1.0;
//invariant
if(n<0)
return 1.0/pow(x,n); //-n改为n
else
return pow(x,n);
}

private double pow(double x,int n){
//bound
if(n==0)
return 1;
double v=pow(x,n/2);
if(n%2==0)
return v*v;
else
return v*v*x;
}
}

感谢エリザベス兄弟给予的无私支持!!