selected_coding_interview/docs/50. Pow(x, n).md
求 $x^n$ 最简单的方法是通过循环将 $n$ 个 $x$ 乘起来,依次求 $x^1, x^2, ..., x^{n-1}, x^n$ ,时间复杂度为 $O(n)$ 。 快速幂法 可将时间复杂度降低至 $O(\log n)$ ,以下从 “二分法” 和 “二进制” 两个角度解析快速幂法。
利用十进制数字 $n$ 的二进制表示,可对快速幂进行数学化解释。
$$ x^{2^{i-1}b_i}= \begin{cases} 1 & , b_i = 0 \ x^{2^{i-1}} & , b_i = 1 \ \end{cases} $$
{:width=450}
快速幂实际上是分治思想的一种应用。
$$ x^n = \begin{cases} (x^2)^{n//2} & , n 为偶数 \ x(x^2)^{n//2} & , n 为奇数 \ \end{cases} $$
观察发现,当 $n$ 为奇数时,二分后会多出一项 $x$ 。
{:width=450}
Java 代码中
int32变量 $n \in [-2147483648, 2147483647]$ ,因此当 $n = -2147483648$ 时执行 $n = -n$ 会因越界而赋值出错。解决方法是先将 $n$ 存入long变量 $b$ ,后面用 $b$ 操作即可。
class Solution:
def myPow(self, x: float, n: int) -> float:
if x == 0.0: return 0.0
res = 1
if n < 0: x, n = 1 / x, -n
while n:
if n & 1: res *= x
x *= x
n >>= 1
return res
class Solution {
public double myPow(double x, int n) {
if(x == 0.0f) return 0.0d;
long b = n;
double res = 1.0;
if(b < 0) {
x = 1 / x;
b = -b;
}
while(b > 0) {
if((b & 1) == 1) res *= x;
x *= x;
b >>= 1;
}
return res;
}
}