50. Pow(x, n)
Total Accepted: 85668
Total Submissions: 307134
Difficulty: Medium
下面给出的两种解法时间复杂度都为logn。
解法1:二分法
最容易想到的是这个方法。注意一下幂次奇偶性。
代码如下(已AC):
// 二分求解 这里幂n > 0
static double powhelper(double x, int n)
{
if (n == 0)
return 1;
double res = powhelper(x, n / 2);
if (n % 2 == 0)
return res * res;
else
return res * res * x;
}
double myPow(double x, int n)
{
// 二分实现 logn
if (n == 0)
return 1;
else if (n < 0)
return 1.0 / powhelper(x, -n);
return powhelper(x, n);
}
解法2:位运算
其实这种方法和上面思想类似。将n转换为以2为底的一系列数之和。
从低位迭代至高位。这里需要考虑一些边界溢出的情况,需要注意一下。
【注:Leetcode目前的test case里面增加了很多测试边界溢出的用例
算法设计时需要将边界情况考虑完全】
代码如下(已AC):
(很疑惑 limits头文件中定义的DBL_MAX 和 DBL_MIN在OJ上居然undefined)
double myPow(double x, int n)
{
#define DBL_MAX 1.7976931348623158e+308
#define DBL_MIN 2.2250738585072014e-308
// 位运算实现
if (n == 0) return 1;
else
{
double res = 1.0;
if (n < 0)
{
//x = 1.0 / x; // ?
// 这段代码防止x=0 那么/x就无意义
if (x >= 1.0 / DBL_MAX || x <= 1.0 / -DBL_MAX)
{
x = 1.0 / x;
}// end if
else
{
return DBL_MAX;
}//end else
// 现在leetcode 测试数据case里面有 n = INT_MIN的用例
// 所以增加了下面的边界判断
if (n == INT_MIN)
{
n++;
res *= x;
}
n = -n;
}// end if
bool neg = false; // 结果是否为负数
if (x < 0)
{
x = -x;
if (n % 2)
{
neg = true;
}
}// end if
while (n)
{
if (n & 1)
{
// 一定需要溢出判断
if (res > (numeric_limits<double>::max)() / x)
{
return (numeric_limits<double>::max)();
}
res *= x;
}
x *= x;
n >>= 1;
}// end while
return neg ? -res : res;
}// end else
}
【注:
边界溢出的几个点
a. x = 0
b. n < 0
c. n == INT_MIN
d. x < 0
】