leetcode 50. Pow(x, n) 中等
要特别注意 n 的范围 ,如果 n = -2^31,使用int 是不可以直接 n = -n; 的
一、使用long
这里做的时候没注意到已经使用了pow,所以这题可以说使用long做出来
class Solution {
public:
double myPow(double x, int n) {
if(x == 0) return 0;
if(n == 0) return 1;
if(n == 1) return x;
if(x == 1) return 1;
long nTemp = n;
if(nTemp < 0){
x = 1.0/x;
nTemp = -nTemp;
}
double res = 1.0;
long count = 0;
vector<double> mult;
mult.push_back(x);
//比如n = 35,那么两两平方的次数为log(35)向下取整
//x^1 x^2 x^4 x^8 x^16 x^32 最多平方5次
int log2 = (int)(log(nTemp)/log(2));
for(int i = 0;i < log2;i++){
double t = mult.back();
mult.push_back(t*t);
}
int size = mult.size();
for(int i = size-1;i >= 0;i--){
if(count + pow(2,i) <= nTemp){
res *= mult[i];
count += pow(2,i); //count代表目前res=x^count
//没留意到这里已经使用了pow,属于违反条件了
}
}
return res;
}
};
二、不使用long
不使用long就要对边界条件单防了。
class Solution {
public:
//单独计算小范围的2^n
int pow2(int n){
if(n == 0) return 1;
int res = 1;
while(n > 0){
res *= 2;
n--;
}
return res;
}
double myPow(double x, int n) {
if(x == 0) return 0;
if(n == 0) return 1;
if(n == 1) return x;
if(x == 1) return 1;
if(x == -1){
if(n == INT_MIN) return 1;
if(n < 0) n = -n;
if(n%2==0) return 1;
else return -1;
}
if(n == INT_MIN){
if(abs(x)>1) return 0;
return (1.0/x)*myPow(1.0,INT_MAX);
}
if(n < 0){
x = 1.0/x;
n = -n;
}
double res = 1.0;
int count = 0;
vector<double> mult;
mult.push_back(x);
int log2 = (int)(log(n)/log(2));
for(int i = 0;i < log2;i++){
double t = mult.back();
mult.push_back(t*t);
}
int size = mult.size();
for(int i = size-1;i >= 0;i--){
if(count + pow2(i) <= n){
res *= mult[i];
count += pow2(i);
}
}
return res;
}
};
我的这种用vector来保存2^k次方的做法对内存消耗还是很大的
题解
一、快速幂 + 递归
class Solution {
public:
double quickMult(double x,long n){
if(n == 0) return 1;
double y = quickMult(x,n/2);
if(n % 2 == 0) return y*y;
else return y*y*x;
}
double myPow(double x, int n){
long N = n;
return N > 0 ? quickMult(x,N) :quickMult(1.0/x,-N);
}
};
二、快速幂 + 迭代
我原本的做法跟这个有点类似,我使用vector本质就是想把这里说的有贡献的2^k次方保存起来
这个方法的关键就是 , 根据 n 的二进制 ,1 的位置所代表的次方就是有贡献的
class Solution {
public:
double quickMult(double x,long n){
if(n == 0) return 1;
if(x == 1) return 1;
if(x == 0) return 0;
double res = 1.0;
double x_contribute = x;
while(n > 0){
if(n % 2 == 1) res *= x_contribute;
x_contribute *= x_contribute;
n /= 2;
}
return res;
}
double myPow(double x, int n){
long N = n;
return N > 0 ? quickMult(x,N) :quickMult(1.0/x,-N);
}
};