题目:
Implement pow(x, n).
没有特殊要求,根据题目要求的输入,是(double x, int n)
,那么最大的阶数是MAX_INT,最小的阶数是MIN_INT。
首先想到的是,一个while循环,res*=x
就可以了,但是会超时TLE。那么就要想一个比O(n)复杂度更小的算法了。
不难想到,计算过程中,有的计算结果是可以储存下来供后面的计算用的,比如已经计算了x^3
, 那么x^15=(x^3)^5
,但是3次方对于编程不太友好,为了方便,使用x^2。
平方的好处在于每次计算只需要乘以数的自己就可以了,我们还知道十进制数转换到二进制的一种多项式方法,就是x^15 = x^8 * x^4 * x^2 * x
,计算x^8
的过程中,会产生x, x^2, x^4
等数,用一个数组存起来,当计算到x^8
的时候,遍历数组找到它们即可。
根据以上想法,我的代码如下:
double Solution::myPow(double x, int n) {
vector<double> fx; // 使用数组记录低阶的计算结果
double res = 1;
int nagetive = 1;
long long int _n = n; // 使用更大的类型以储存 (0 - INT_MIN)
if (_n == 0) return res;
if (_n < 0) {
nagetive = -1;
_n = 0 - _n;
}
int e = 1; // 2^e, e∈Z+
fx.push_back(res); // x^0
res *= x;
fx.push_back(res); // x^1
while (_n > 0) {
/* 找到最大的2的e次方,满足对n的分解:
n = 2^e + k1*2^(e - 1) + ... + ke*2^0
其中 k1~ke ∈ {0, 1}*/
if (_n > pow(2, e)) {
res *= fx.back(); // x^2, x^4, ..., x^(2^e)
fx.push_back(res);
e++;
}
else {
/* 找到最大的e之后找剩下的阶数 */
_n -= pow(2, e - 1);
for (int i = e - 1; _n > 0; i--) {
if (_n >= pow(2, i)) {
_n -= pow(2, i);
res *= fx[i + 1]; // 从数组获取低阶的计算结果
}
}
break;
};
}
if (nagetive == -1) res = 1 / res;
return res;
}