50. Pow(x, n)
实现 pow(x, n) ,即计算 x 的 n 次幂函数。
示例 1:
输入: 2.00000, 10
输出: 1024.00000
示例 2:
输入: 2.10000, 3
输出: 9.26100
示例 3:
输入: 2.00000, -2
输出: 0.25000
解释: 2^-2 = (1/2)^2 = 1/4 = 0.25
说明:
-100.0 < x < 100.0
n 是 32 位有符号整数,其数值范围是 [−2^31, 2^31 − 1] 。
分析:
(1)对于负指数情况的处理:
我们希望对于负指数情况的处理,可以像正指数情况那样,采用一样方法进行处理。
对于 pow(3, -7)的情况,我们可以将其转换为 pow(1/3, 7),即我们将指数 -n 中的负号,移动到 x 上 , 将 x 转换为 x ^ -1 。这样,对于负指数情况的处理,可以像正指数情况那样,采用一样方法进行处理。
(2)关于负数转换为正数,范围越界的处理
关于(1)中对于负指数情况的处理,会存在边界问题,即int范围中,负数比正数多一个数。若将 -n 直接变成 n ,在 -n 为 −2^31 时, n 为 2^31,超出了int的范围。
令 n’ = n+1 = -2147483647 。求x^n等价于求 x^n’ * x-1
即我们先拿出一个 1/x 出来,然后再尽心符号的变换,这样就可以避免越界的情况出现了。
(3)递归思想:
递归思想非常的简单,
当 n 为偶数时, 先递归求出指数为一半的值, half = myPow(x, n >> 1); 返回 half *= half; 计算后的half 即可,
当n 为奇数时,先递归求出指数为一半的值, half = myPow(x, n >> 1); 返回 half *= half; half *= x; 计算后的half 即可,
递归代码:
class Solution {
public:
double myPow(double x, int n) {
if (n < 0)
return 1 / x * myPow(1 / x, -(n + 1));
else if (n == 0)
return 1;
double half = myPow(x, n >> 1);
half *= half;
if ((n & 1) == 1)
half *= x;
return half;
}
};
(4)非递归思想:
任何一个int数,都可以用32为的二进制01表示。
例如: 当我们要求解pow(3, 7)时,7的二进制为111,三个1分别代表1,2,4。所以3^7 可以分解为:3^1 * 3^2 * 3^4 。
因此我们只需要判断 n 的二进制数中哪些位为1,然后分别乘上x的相应指数倍即可。
在循环的过程中,我们一直使用tmp来记录在当前位上,x的相应指数倍的值。
非递归代码:
class Solution {
public:
double myPow2(double x, int n)
{
double ans = 1.0;
double tmp = x;
while(n)
{
if((n & 1))
{
ans *= tmp;
}
tmp *= tmp;
n = n>>1;
}
return ans;
}
double myPow(double x, int n) {
if (n == 0) return 1;
else if (n < 0)
return 1 / x * myPow2(1 / x, -(n + 1));
else return myPow2(x, n);
}
};