这题看似简单,其实有许多需要注意的。
- 考虑全面。需要考虑base、exponent是0,正数、负数的情况。
- 算法的优化:power1解法时间复杂度是o(n),其实下边还应该再思考,看是否能缩短时间复杂度。这时就可以从for循环这改进。a的8次方可以分为a的2次方*a的4次方,而a的4次方又可以分为两个a的2次方的相乘。这样和之前的斐波那契数列想似,我们就可以使用递归了。公式为
- 当n为偶数,a^n =(a^n/2)*(a^n/2)
- 当n为奇数,a^n = a^[(n-1)/2] * a^[(n-1)/2] * a
- 算法的在优化:其实大部分递归均能修改成迭代,这样能进一步减少时间复杂度。
- 注意的细节:使用右移运算代替除以2,加快运算速度。还有计算机中double、float表示的0会有误差,使用==0的时候,可以自己写一个函数来判断。
package problem11;
public class doublePower {
double Power(double base, int exponent) {
double result=1.0;
if(base == 0){
return 0;
}else{
int absExponent = exponent;
if(exponent<0) absExponent = -exponent;
for(int i = 0;i <absExponent; i++){
result *= base;
}
if(exponent<0)
result = 1/result;
}
return result;
}
double Power2(double base, int exponent) {
double result=1.0;
if(base == 0){
result = 0;
}else{
int absExponent = exponent;
if(exponent==0) return 1;
if(exponent<0) absExponent = -exponent;
result = Power2(base,absExponent>>1);//使用右移代替除2,减少时间浪费
result *= result;
if((absExponent&1) == 1){
result *= base;//如果最后指数剩下1了或者exponent是奇数的时候,直接*base
}
if(exponent<0)
result = 1/result;
}
return result;
}
double Power3(double base, int exponent) {
int p = exponent;
if(exponent<0) p = -exponent;
double r = 1.0;
while(p>0){
if((p&1)==1) r *= base;
base *= base;
p >>= 1;
}
return exponent < 0 ? 1/ r : r;
}
public static void main(String[] args) {
// TODO Auto-generated method stub
doublePower p = new doublePower();
double a = p.Power3(2, 0);
System.out.println(a);
}
}