暴力法
pow(x,n)就是n个x相乘,直接使用循环暴力计算,时间复杂度为O(n),在LeetCode的提交后容易超时。
double pow1(double x,int n){
long long N = n;
if(x == 0) return 0;
if(x == 1 ||n ==0) return 1.0;
if(N<0){
N = -n;
x = 1/x;
}
double ans = 1.0;
for(int i =0;i<N;++i){
ans*=x;
}
return ans;
}
快速幂+递归
快速幂算法本质是二分法,在求x的n次方时,我们只需要算出x的(n/2)次方即可。当n为偶数时,则x^n = x^(n/2) * x^(n/2);当n为奇数时,x^n = x^(n/2)*x^(n/2)*x即可。
double powHelp(double x,long long n){
if(n == 0) return 1.0;
double half = powHelp(x,n/2);
return n%2 == 0?half*half:half*half*x;
}
double pow2(double x,int n){
long long N = n;
if(x == 0) return 0;
if(x == 1 ||n ==0) return 1.0;
return n>0?powHelp(x,n):1/powHelp(x,-n);
}
快速幂 +迭代
对于任意一个数n,都有他自己的二进制形式,也即是说,对于一个数n,它可以拆分以下形式:
例如,对于77,它的二进制为 0100 1101,它拆分为以下形式
而对于x^77次方则可以分解为以下形式:
则可以使用求2进制的方法对x进行倍乘,进而求得x^77的结果。
// 迭代法
double quickPow2(double x,uint32_t n){
double ans = 1.0;
// 根据x的二进制中1的位置来倍乘x
double x_con = x;
while(n>0){
// 当二进制位为1的时候,将x_con乘入答案
if(n%2 == 1) ans*=x_con;
// 每次进一位,x_con的值就要倍乘
x_con*=x_con;
n/=2;// 求下一个二进制位
}
return ans;
}
double myPow(double x, int n) {
long long N = n;
if(N == 0 || x == 1) return 1.0;
if(N == 0) return 0;
return n>0?quickPow2(x,N):1.0/quickPow2(x,-N);
}