方法一:递归。
指数可能有两种:自然数或者负数,对于负数情况依然可以按照自然数情况计算,只是最后需要1.0/res即可。
x→x2→x4→x8→x16→x32→x64
x→x*2→x4→x9→x19→x38→*x77
当我们试图从左往右计算时,无法确定当前是直接平方,还是平方后依然要乘以x。为了解决这种困境,我们采用从右往左的方式计算,每次只需要判断指数是奇数还是偶数,如果是偶数直接将结果平方,否则平方后再乘x
class Solution {
public double myPow(double x, int n) {
long N = n;
// 自然数 or 负数,两种情况
return N >= 0 ? quickMul(x, N) : 1.0 / quickMul(x, -N);
}
public double quickMul(double x, long N) {
if (N == 0) {
return 1.0;
}
double y = quickMul(x, N / 2);
// 指数是偶数 or 奇数 两种情况
return N % 2 == 0 ? y * y : y * y * x;
}
}
方法二:迭代。
在迭代方法中就需要从左往右计算,但是刚刚说了从左往右计算所面临的困难,所以尝试另一种做法。
通过计算和观察发现,77的二进制值是(1001101)2,而x77 = x * x4 * x8 * x64 ,所以得出结论:
若 n = 2i0 + 2 i1 + .... + 2in
则 x = x2i0 * x2i1 * ... * x2in
class Solution {
public double myPow(double x, int n) {
long N = n;
return N >= 0 ? quickMul(x, N) : 1.0 / quickMul(x, -N);
}
public double quickMul(double x, long N) {
double res = 1.0;
double x_contribute = x;
while (N > 0) {
// 判断指数的最后一位是否是1,x_contribute就表示当前位的2^n
if ((N & 1) != 0) {
res *= x_contribute;
}
x_contribute *= x_contribute;
// y
N /= 2;
}
return res;
}
}