1 题目描述
实现函数double Power(double base, int exponent),求base的exponent次方。不得使用库函数,同时不需要考虑大数问题。
示例1:
输入: 2.00000, 10
输出: 1024.00000
示例2:
输入: 2.10000, 3
输出: 9.26100
示例3:
输入: 2.00000, -2
输出: 0.25000
解释: 2^-2 = 1/2^2 = 1/4 = 0.25
说明:
-100.0 < x < 100.0
n 是 32 位有符号整数,其数值范围是
[
−
2
31
,
2
31
−
1
]
[−2^{31}, 2^{31} − 1]
[−231,231−1] 。
2 解题思路
求 x n x^n xn最简单的方法是通过循环将n个x乘起来,依次求 x 1 , x 2 , . . . , x n − 1 , x n x^1,x^2,...,x^{n-1},x^n x1,x2,...,xn−1,xn,时间复杂度为O(n)。
快速幂法可将时间复杂度降低至 O ( l o g 2 n ) O(log_2n) O(log2n),以下从“二分法”和“二进制”两个角度解析快速幂法。
快速幂解析(二进制角度):
利用十进制数字n的二进制表示,可对快速幂进行数字化解释。
- 对于任何十进制正整数n,设其二进制为“
b
m
.
.
.
b
3
b
2
b
1
b_m...b_3b_2b_1
bm...b3b2b1”(
b
i
b_i
bi为二进制某位值,
i
∈
[
1
,
m
]
i \in [1,m]
i∈[1,m]),则有:
- 二进制转十进制: n = 1 b 1 + 2 b 2 + 4 b 3 + . . . + 2 m − 1 b m n=1b_1+2b_2+4b_3+...+2^{m-1}b_m n=1b1+2b2+4b3+...+2m−1bm(即二进制转十进制公式);
- 幂的二进制展开: x n = x 1 b 1 + 2 b 2 + 4 b 3 + . . . + 2 m − 1 b m = x 1 b 1 x 2 b 2 x 4 b 3 . . . x 2 m − 1 b m x^n=x^{1b_1+2b_2+4b_3+...+2^{m-1}b_m}=x^{1b_1}x^{2b_2}x^{4b_3}...x^{2^{m-1}b_m} xn=x1b1+2b2+4b3+...+2m−1bm=x1b1x2b2x4b3...x2m−1bm;
- 根据以上推导,可把计算
x
n
x^n
xn转化为解决以下两个问题:
- 计算 x 1 , x 2 , x 4 , . . . , x 2 m − 1 x^1,x^2,x^4,...,x^{2^{m-1}} x1,x2,x4,...,x2m−1的值:循环赋值操作 x = x 2 x=x^2 x=x2即可;
- 获取二进制各位
b
1
,
b
2
,
b
3
,
.
.
.
,
b
m
b_1,b_2,b_3,...,b_m
b1,b2,b3,...,bm的值:循环执行以下操作即可。
- n&1(与操作):判断n二进制最右一位是否为1;
- n>>1(移位操作):n右移一位(可理解为删除最后一位)。
- 因此,应用以上操作,可在循环中依次计算
x
2
0
b
1
,
x
2
1
b
2
,
.
.
.
,
x
2
m
−
1
b
m
x^{2^0b_1},x^{2^1b_2},...,x^{2^{m-1}b_m}
x20b1,x21b2,...,x2m−1bm的值,并将所有
x
2
i
−
1
b
i
x^{2^{i-1}b_i}
x2i−1bi累积相乘即可。
- 当 b i = 0 b_i=0 bi=0时: x 2 i − 1 b i = 1 x^{2^{i-1}b_i}=1 x2i−1bi=1;
- 当 b i = 1 b_i=1 bi=1时: x 2 i − 1 b i = x 2 i − 1 x^{2^{i-1}b_i}=x^{2^{i-1}} x2i−1bi=x2i−1;
class Solution {
public double myPow(double x, int n) {
if (x == 0) return 0;
if (n < 0) {
x = 1 / x;
n = -n;
}
double res = 1;
while (n != 0) {
if ((n & 1) != 0) res *= x;
x *= x;
n >>>= 1;
}
return res;
}
}
复杂度分析:
- 时间复杂度 O ( l o g 2 n ) O(log_2 n) O(log2n) : 二分的时间复杂度为对数级别。
- 空间复杂度 O(1) : res, b 等变量占用常数大小额外空间。