Pow(x, n)

实现 pow(x, n) ,即计算 x 的 n 次幂函数。
示例 1:

输入: 2.00000, 10
输出: 1024.00000

示例 2:

输入: 2.10000, 3
输出: 9.26100

示例 3:

输入: 2.00000, -2
输出: 0.25000
解释: 2-2 = 1/22 = 1/4 = 0.25

说明:
-100.0 < x < 100.0
n 是 32 位有符号整数,其数值范围是 [−231, 231 − 1] 。

解题思路:

暴力:根据幂次,将底数自乘幂次(n次),循环得到结果,负数指数也只是正数结果分之一,这种方法不用想就知道肯定超时的
改进暴力:折半计算,当指数为偶数(n %20)时,就是\(x^n = x ^{(n/2)^2}\) ,如求2的8次幂,就等于2的4次幂的平方,而2的4次幂有等于2的2次幂的平方,2的2次幂有等于2的一次幂的平方,2的一次幂就等于2的0次幂的平方再乘与2也就是2本身;当指数为奇数时(n % 21),除了上述的平方外,还需要再乘一次底数x
通过折半计算,每次把n减半,降低了空间复杂度,也降低了时间复杂度

class Solution {
public:
    double myPow(double x, int n) {
        double res = 1.0;
        for(int i = n; i != 0; i /= 2){
            if(i % 2 != 0){
                res *= x;
            }
            x *= x;
        }
        return  n < 0 ? 1 / res : res;
    }
};

快速幂+递归
快速幂算法」的本质是分治算法。举个例子,如果我们要计算 \(x^{64}\),我们可以按照:

\[x \to x^2 \to x^4 \to x^8 \to x^{16} \to x^{32} \to x^{64} \]

的顺序,从 xx 开始,每次直接把上一次的结果进行平方,计算 66 次就可以得到 \(x^{64}\)的值,而不需要对 x乘 63次 x。
再举一个例子,如果我们要计算 \(x^{77}\),我们可以按照:

\[x \to x^2 \to x^4 \to x^9 \to x^{19} \to x^{38} \to x^{77} \]

的顺序,在\(x \to x^2,x^2 \to x^4,x^19 \to x^38\)这些步骤中,我们直接把上一次的结果进行平方,而在 \(x^4 \to x^9,x^9 \to x^19,x^38 \to x^7\)这些步骤中,我们把上一次的结果进行平方后,还要额外乘一个x。
直接从左到右进行推导看上去很困难,因为在每一步中,我们不知道在将上一次的结果平方之后,还需不需要额外乘 xx。但如果我们从右往左看,分治的思想就十分明显了:

  • 当我们要计算\(x^n时,我们可以先递归地计算出 y = x^{\lfloor n/2 \rfloor},其中 \lfloor a \rfloor 表示对 a 进行下取整;\)
  • \(根据递归计算的结果,如果 n 为偶数,那么 x^n = y^2;如果 n 为奇数,那么 x^n = y^2 * x\)
  • 递归的边界为 n = 0n=0,任意数的 00 次方均为 1
class Solution {
public:
    double quickMul(double x,long long N)
    {
        if(N == 0)
            return 1.0;
        double y = quickMul(x,N/2);
        return N % 2 == 0?y*y:y*y*x;        
    }

    double myPow(double x, int n) {
        long long N = n;
        return  N >= 0?quickMul(x,N):1.0/quickMul(x,-N);
    }
};
posted @ 2020-08-07 21:06  牛犁heart  阅读(269)  评论(0编辑  收藏  举报