11.3 Pow(x, n)【50】
11.3.1 题目描述
实现 pow(x, n),即计算 x
的整数 n
次幂函数(即,xn
)。
11.3.2 方法一:快速幂 + 递归
前言
本题的方法被称为「快速幂算法」,有递归和迭代两个版本。这篇题解会从递归版本的开始讲起,再逐步引出迭代的版本。
当指数 nn 为负数时,我们可以计算
x
−
n
x^{-n}
x−n 再取倒数得到结果,因此我们只需要考虑 n 为自然数的情况。
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) {
if (N == 0) {
return 1.0;
}
double y = quickMul(x, N / 2);
return N % 2 == 0 ? y * y : y * y * x;
}
}
复杂度分析
- 时间复杂度:O(logn),即为递归的层数。
- 空间复杂度:O(logn),即为递归的层数。这是由于递归的函数调用会使用栈空间。
11.3.3 方法二:快速幂 + 迭代
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 ans = 1.0;
// 贡献的初始值为 x
double x_contribute = x;
// 在对 N 进行二进制拆分的同时计算答案
while (N > 0) {
if (N % 2 == 1) {
// 如果 N 二进制表示的最低位为 1,那么需要计入贡献
ans *= x_contribute;
}
// 将贡献不断地平方
x_contribute *= x_contribute;
// 舍弃 N 二进制表示的最低位,这样我们每次只要判断最低位即可
N /= 2;
}
return ans;
}
}
复杂度分析
- 时间复杂度:O(log n),即为对 n 进行二进制拆分的时间复杂度。
- 空间复杂度:O(1)。
11.3.4 my answer—递归
class Solution {
public double myPow(double x, int n) {
if(n==0){
return 1.0;
}else if(n<0){
if(n%2==0){
return myPow(x,n/2)*myPow(x,n/2);
}else{
return (1.0/x)*myPow(x,(n+1)/2)*myPow(x,(n+1)/2);
}
}else{
if(n%2==0){
return myPow(x,n/2)*myPow(x,n/2);
}else{
return x*myPow(x,n/2)*myPow(x,n/2);
}
}
}
}