快速幂思路分析和代码实现

快速幂

  • 快速幂 就是快速算底数的n次幂。其时间复杂度为 O ( l o g N ) O(logN) O(logN)

对于普通的计算 x的n次方, x n x^n xn , 我们一般的计算方法就是将x相乘n次得到最后的结果, 这样的时间复杂度为 O ( N ) O(N) O(N), 但是

快速幂可以在时间复杂度为 O ( l o g N ) O(logN) O(logN) 计算出结果, 下面看其原理 :

来举一个例子, 例如我们计算 3 7 3^7 37 的结果, 我们可以先预处理一些数据:

预处理数据:
3 2 0 3^{2^0} 320 = 3, 3 2 1 3^{2^1} 321 = 9, 3 2 2 3^{2^2} 322 = 81, 再往后面枚举 3 2 3 3^{2^3} 323 = 3 8 3^8 38 > 3 7 3^7 37, 故后面的都不需要枚举了.

然后我们再来计算
3 7 3^7 37 = 3 2 2 + 2 1 + 2 0 3^{2^2 + 2^1 + 2^0} 322+21+20 = 3 2 2 3^{2^2} 322 × \times × 3 2 1 3^{2^1} 321 × \times × 3 2 0 3^{2^0} 320 = 2187;

其中 7 = 2 2 + 2 1 + 2 0 2^2 + 2^1 + 2^0 22+21+20 , 其实就是将7转化成十进制就是 0b111

我们看整个过程只计算了多少次, 3 2 0 3^{2^0} 320 = 3, 3 2 1 3^{2^1} 321 = 9, 3 2 2 3^{2^2} 322 = 81, 只有3次, 且计算第k个值的时候, 是由前面k - 1值的平方得到的。 如果换成换成 K, 计算 3 k 3^k 3k

那么同样:
3 2 0 3^{2^0} 320 = 3, 3 2 1 3^{2^1} 321 = 9, 3 2 2 3^{2^2} 322 = 81, …, 3 2 l o g 2 k 3^{2^{log2k}} 32log2k, 故预处理一共计算 logk + 1次。

最后计算 3 k 3^k 3k = 3 2 a + 2 b + 2 c + . . . . . 3^{2^a + 2^b + 2^c + .....} 32a+2b+2c+..... = 3 2 a 3^{2^a} 32a × \times × 3 2 b 3^{2^b} 32b × \times × 3 2 c 3^{2^c} 32c × 3 2 d \times 3^{2^d} ×32d

其实整个计算过程可以边预处理边进行.

// 这里只是简单考虑 n > 0 的情况 
double myPow(double x, int n)        // x即为初始的 x的2的0次方,即第一个预处理值
{
    double res = 1; 
    while(n)
    {
        if(n & 1) res *= x;          // 从低位判断这位是否为1, 若为1,说明最后的结果是要乘上目前的预处理值
        n >>= 1;                     // 最低位右移移出
        x *= x;                      // 计算预处理值中,本次的值是由前面计算的预处理值的平方得到 
    }
    return res; 
}

相关题目

题目链接 : Leetcode 50.快速幂

题目描述

实现 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 -100.0 < x < 100.0 100.0<x<100.0

  • − 2 31 ≤ n ≤ 2 31 − 1 -2^{31} \le n \le 2^{31}-1 231n2311

  • − 1 0 4 ≤ x n ≤ 1 0 4 -10^4 \le x^n \le 10^4 104xn104

算法 (快速幂)
思路分析

这里 n 有可能小于0, 故当n < 0 时候, 此时底数我们应该将传入的x, 取一个倒数.

C++ 代码
class Solution 
{
public:
    double myPow(double x, int n) 
    {
        long long k = n; 
        if(k < 0) x = 1 / x, k = -k;
        double res = 1; 
        while(k)
        {
            if(k & 1) res *= x;
            k >>= 1; 
            x *= x; 
        }
        return res; 
    }
};
时间复杂度 O ( l o g n ) O(logn) O(logn)

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值