Go&Java算法之数值的整数次方

185 阅读1分钟

这是我参与2022首次更文挑战的第11天,活动详情查看:2022首次更文挑战

数值的整数次方

实现 pow(x, n) ,即计算 x 的 n 次幂函数(即,xn)。不得使用库函数,同时不需要考虑大数问题。

示例 1:

输入:x = 2.00000, n = 10

输出:1024.00000

示例 2:

输入:x = 2.10000, n = 3

输出:9.26100

示例 3:

输入:x = 2.00000, n = -2

输出:0.25000

解释:2-2 = 1/22 = 1/4 = 0.25  

提示:

-100.0 < x < 100.0

-231 <= n <= 231-1

-104 <= xn <= 104

题解

算法一:快速幂(Java)

比如要求x^11,正常的乘积需要循环乘11次,时间复杂度为O(n)

快速幂的思想就是将指数11 可以转成二进制数1011,则原来的式子可以转化成

x^{11} = x^{2^{3} + 2^{1} + 2^{0}} = x^{2^{3}} * x^{2^{1}} * x^{2^{0}},此时只运算了3次乘积,时间复杂度降至O(logn)

下方代码中的x *= x是一个累乘的过程,得到四位二进制数,对应的四个权重,x,x *= x,x^2 *= x^2, x^4 *= x^4

1011二进制数,从右至左分别为1 1 0 1 ,只有在1的位置上,才有相应的权重,这也就是为什么需要通过与运算:(b & 1) == 1判断最后一位是否为1。

x ---> x^{2^{0}}x---------> 1

x^2 ---> x^{2^{1}}x-------------> 1

x^4 ---> x^{2^{2}}x-----------------> 0

x^8 ---> x^{2^{3}}x-----------------------> 1

最终的结果就是将每一位的1 所对应的权重相乘即可:x^{2^{0}} * x^{2^{1}} * x^{2^{3}}

class Solution {
    public double myPow(double x, int n) {
        if(n == 0) {
            return 1;
        }
        long b = n;
        if(b < 0) {
            x = 1 / x;
            b = -b;
        }
        double res = 1;
        while(b > 0) {
            if((b & 1) == 1) {
                res *= x;
            }
            x *= x;
            b >>= 1;
        }
        return res;
    }
}

时间复杂度:O(log2N)

空间复杂度:O(1)

算法一:快速幂(Go)

思路同上

func myPow(x float64, n int) float64 {
    if n == 0 {
        return 1.0
    }else if n <0 {
        return 1.0 / myPow(x,-n)
    }
    temp:= myPow(x,n/2)
    if n%2 ==0 { return temp *temp }
    return x *temp *temp 
}

时间复杂度:O(log2N)

空间复杂度:O(1)