快速幂
- 快速幂 就是快速算底数的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 −231≤n≤231−1
-
− 1 0 4 ≤ x n ≤ 1 0 4 -10^4 \le x^n \le 10^4 −104≤xn≤104
算法 (快速幂)
思路分析
这里 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;
}
};