题目描述
实现函数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/22 = 1/4 = 0.25
说明:
- -100.0 < x < 100.0
- n 是 32 位有符号整数,其数值范围是 [−231, 231 − 1] 。
解题思路
通常求xn最简单的方法是连续将n个x相乘,依次求x1,x2,x3……x(n-1),xn,时间复杂度O(n)。
而采用快速幂法可以将时间复杂度降低到O(log2n)
快速幂解析(二分法角度)
x n = x n / 2 × x n / 2 = ( x 2 ) n / 2 x^n = x^{n/2}×x^{n/2}=(x^2)^{n/2} xn=xn/2×xn/2=(x2)n/2,令n/2为整数,考虑奇偶两种情况,设向下取整数符号为//
- 当n为偶数时: x n = ( x 2 ) n / / 2 x^n=(x^2)^{n//2} xn=(x2)n//2;
- 当n为奇数时: x n = x ( x 2 ) n / / 2 x^n=x(x^2)^{n//2} xn=x(x2)n//2;
设res初始值为1,开始进行循环二分。举例如下:
循环 | x n × ( r e s ) x^n\times(res) xn×(res) |
---|---|
第0轮 | 3 5 × ( 1 ) 3^5\times(1) 35×(1) |
第1轮 | 9 2 × ( 1 × 3 ) 9^2\times(1\times3) 92×(1×3) |
第2轮 | 8 1 1 × ( 1 × 3 ) 81^1\times(1\times3) 811×(1×3) |
第3轮 | 656 1 0 × ( 1 × 3 × 81 ) 6561^0\times(1\times3\times81) 65610×(1×3×81) |
返回 | 1 × 3 × 81 1\times3\times81 1×3×81 |
计算流程:
- 当x=0时,直接返回0。
- 初始化res=1;
- 当n<0时,将其转化为 n ≥ 0 n\ge0 n≥0的范围内,x=1/x,n=-n;
- 循环:当n=0时跳出
- 当n%2 = 1时,奇数时res*=x(将当前x乘入res)
- x*=x,即 x = x 2 x=x^2 x=x2
- n/=2,向下整除,n//2
int类型变量 n ∈ [ − 2147483648 , 2147483647 ] n\in[-2147483648, 2147483647] n∈[−2147483648,2147483647], 因此当 n=−2147483648 时执行 n = -n 会因越界而赋值出错。解决方法是先将 n 存入 long 变量 b ,后面用 b 操作即可。
class Solution {
public double myPow(double x, int n) {
if(x == 0) return 0;
long b = n;
double res = 1.0;
if(b < 0) {
x = 1 / x;
b = -b;
}
while(b > 0) {
if((b % 2) == 1) res *= x;
x *= x;
b /= 2;
}
return res;
}
}