剑指offer-16 数值的整数次方
微信搜索【程序员画工师】关注更多Java编程技术、数据结构与算法、面试题相关内容。
题目
给定一个double类型的浮点数base和int类型的整数exponent。求base的exponent次方。保证base和exponent不同时为0。
思路1
当指数为正数的时候,base相乘exponent次即可;考虑到指数为负数的情况,就要先对指数求绝对值,算出次方的结果之后再求倒数。而且0不能作为分母,所以当底数为零且指数是负数的时候需要做特殊处理。
上代码
public class Solution {
public double Power(double base, int exponent) {
if(exponent == 0){
return 1;
}
if(exponent == 1){
return base;
}
if(base == 0 && exponent < 0){
throw new RuntimeException("指数为负数时,底数不能为零!");
}
int exp = Math.abs(exponent);
double ret = base;
for(int i = 1;i<exp;i++){
ret = ret * base;
}
if(exponent < 0){
ret = 1 / ret;
}
return ret;
}
}
优化思路
如果输入指数exponent为32,在上面函数的循环中需要循环31次。求一个数字的32次方,那么可以在它16次方的基础上平方即可;而16次方是8次方的平方。依次类推,求32次方只需做5次乘法:平方、4次方、8次方、16次方、32次方。公式如下
递归求解,每次 exponent 缩小一半,时间复杂度为 O(log N)。
上代码
public class Solution {
public double Power(double base, int exponent) {
if(exponent == 0){
return 1;
}
if(exponent == 1){
return base;
}
if(base == 0 && exponent < 0){
throw new RuntimeException("指数为负数时,底数不能为零!");
}
double ret = Power(base, Math.abs(exponent)>>1);
ret = ret * ret;
if((exponent & 1) == 1){ //奇数
ret = ret * base;
}
if(exponent < 0){
ret = 1/ret;
}
return ret;
}
}
在这里用右移运算符实现除以2,用位与运算符判断一个数是奇数还是偶数,是因为位运算的效率比乘除运算及求余运算的效率高得多。
References
[1] 《剑指offer(第二版)》 何海涛著
程序员画工师公众号,获取更多详细Java、Python、C、前端、小程序、产品相关学习资料,欢迎交流