50.Pow(x,n)
1.题目介绍
2.题解
本题的方法被称为「快速幂算法」,有递归和迭代两个版本。这篇题解会从递归版本的开始讲起,再逐步引出迭代的版本。
当指数 n为负数时,我们可以计算 x^-n再取倒数得到结果,因此我们只需要考虑 n 为自然数的情况。
2.1 模拟(不推荐,时间复杂度过高)
思路
分为n>=0, n<0情况分别计算Pow(x,n)
代码
class Solution {
public:
double myPow(double x, int n) {
double ans = 1;
int num = n >=0 ? n:-n;
for(int i = 0; i < num; i++){
ans *= x;
}
if(n < 0) ans = 1.0 / ans;
return ans;
}
};
2.2 快速幂 + 递归
思路
由于每次递归都会使得指数减少一半,因此递归的层数为 O(logn),算法可以在很快的时间内得到结果。
代码
class Solution {
public:
double quickMul(double x, long long N) {
if(N == 0) return 1.0;
double y = quickMul(x, N / 2.0);
return N % 2 == 0? y*y : y*y*x;
}
double myPow(double x, int n) {
long long N = n; // 这里为何要强转为long long? 因为后面-n进行取反时,-2147483648(INT_MIN,整型最小值)进行取反操作,INT_MIN 的取反结果会导致溢出,产生未定义的行为。
return N >= 0 ? quickMul(x, N): 1.0 / quickMul(x, -N);
}
};
2.3 快速幂 + 迭代
思路
由于快速幂的核心理念是每次将上次的结果平方,相当于x(2n) ,但由于在中间乘上额外的x,我们不知道何时触发导致迭代写起来比较麻烦
但是我们仔细观察发现,将初始的x和后面额外乘上的x分开平方
最后化简可以得到
其实就是n的二进制表达式,我们只要n在二进制位为1的值位置
就知道何时要额外乘一个x了
比如像n = 10(1010)是,其实就是2^2 * 2^8
所以我们可以维护一个值专门记录 2^n 的值 x_contributor
当n % 2 == 1时,我们就将结果记录值ans *= x_contributor即可
代码
class Solution {
public:
double quickMul(double x, long long N) {
double ans = 1.0;
double x_contributor = x;
while(N > 0){
if(N % 2 == 1) ans *= x_contributor;
x_contributor *= x_contributor;
N /= 2.0;
}
return ans;
}
double myPow(double x, int n) {
long long N = n;
return N >= 0? quickMul(x,N):1.0 / quickMul(x,-N);
}
};
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· DeepSeek 开源周回顾「GitHub 热点速览」
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了