算法--快速幂

487 阅读2分钟

一、快速幂介绍

求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;
    }
}