一、快速幂介绍
求a^b的值,按照定义的求法就是b个a相乘,如下图
这种方式的时间复杂度是O(n)。 而快速幂就是快速算底数的n次幂,其时间复杂度是 O(log₂N)。
计算方法就是把b转化为二进制数,下图是百度百科示例:
二、Java代码实现(使用int,暂不考虑超过int最大值)
/**
* 快速幂计算
* @param base 底数
* @param index 指数
* @return
*/
public int quickPow(int base, int index){
if (base == 0) {
return 0;
}
int result = 1;
while(index != 0){
if((index & 1) != 0){
result *= base;
}
index = index >> 1;
base *= base;
}
return result;
}
其中,
- 1.因为0的正数幂结果为0,0的负数幂无意义不考虑
- 2.非0底数的0次幂结果为1,所以result的初始值设置为1,while循环判断指数非0的情况;
- 3.利用与运算(&),将指数的二进制数最后一位和1进行与运算判断是否需要累乘此时的底数;
- 4.计算之后,利用右移运算符(>>)将指数二进数向右一位;
- 5.移位之后维护底数的值(base *= base),即base–>base^2–>base^4–>base^8....
三、完善
最近在leetcode上看到相关题目,发现上面的实现只能算是介绍了思想,并不完善(没考虑幂为负数)。所以把leetcode的搬过来:
// 递归实现
class Solution {
public double myPow(double x, int n) {
long N = n;
return N >= 0 ? quickMul(x, N) : 1.0 / quickMul(x, -N);
}
public double quickMul(double x, long N) {
if (N == 0) {
return 1.0;
}
double y = quickMul(x, N / 2);
return N % 2 == 0 ? y * y : y * y * x;
}
}
//复杂度分析
//时间复杂度:O(\log n)O(logn),即为递归的层数。
//空间复杂度:O(\log n)O(logn),即为递归的层数。这是由于递归的函数调用会使用栈空间。
作者:LeetCode-Solution
链接:https://leetcode-cn.com/problems/powx-n/solution/powx-n-by-leetcode-solution/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
“二”中的方法完善:
class Solution {
public double myPow(double base, int power) {
long N = power;
// 判断幂的正负
return N >= 0 ? quickPower(base, N) : 1.0 / quickPower(base, -N);
}
public double quickPower(double base, long power) {
if (base == 0) {
return 0;
}
double result = 1;
while(power != 0){
// power & 1 判断奇偶
if((power & 1) != 0){
//奇数
result *= base;
}
power = power >> 1;
base *= base;
}
return result;
}
}