7.3号更新
解题思路
本题的细节很多
1、要对无效输入进行判断
2、对指数的不同范围分别进行计算
3、计算Pow函数的优化
平常的Pow函数会这么计算
double Power(double base, int exponent) {
double result = 1.0f;
for (int i = 1; i <= exponent; i++) {
result *= base;
}
return result;
}
上述代码的时间复杂度O(n),进一步可以采用如下公式简化
实现代码如下
double PowerWithUnsignedExponent(double base, long exponent) {
if (exponent == 0) return 1.0;
if (exponent == 1) return base;
double result = PowerWithUnsignedExponent(base, exponent >> 1);//为偶数时
result *= result;
if (exponent & 1 == 1)//为奇数时
result *= base;
return result;
}
代码
class Solution {
public:
bool g_InvalidInput = false;//判断是否为无效输入
double myPow(double x, int n) {
if (equal(x, 0.0) && n <= 0) {//无效输入,对于x=0时,n为正数时为0,n为非正数时无意义
g_InvalidInput = true;
return 0.0;
}
double result;
long num = n;
if (n < 0) {//指数小于0
num = -num;
return 1.0 / PowerWithUnsignedExponent(x, num);
}
//指数大于等于0
return PowerWithUnsignedExponent(x, num);
}
double PowerWithUnsignedExponent(double base, long exponent) {
if (exponent == 0) return 1.0;
if (exponent == 1) return base;
double result = PowerWithUnsignedExponent(base, exponent >> 1);//为偶数时
result *= result;
if (exponent & 1 == 1)//为奇数时
result *= base;
return result;
}
bool equal(double n1, double n2) {//浮点数大小判断
if (n1 - n2<0.0000001 && n1 - n2>-0.0000001) return true;//|n1-n2|<p
return false;
}
};
hints
我发现此处使用unsigned int来保存exponent,过不了当int为负的最小值的case
解题思路
本道题目做了很久才通过,感觉有很多的坑等着自己。
首先刚拿到手,觉得题目很简单,开始时,分了两种情况(指数为正和负)+一些特殊情况(底数为0,指数为0)在做
但运行过程中,仍然有报错,第一个错误时n=-2147483648时的错误,刚开始没有反应过来,后来通过题意,才想明白,自己平时做题也没有去考虑过int型的范围,
在n=-2147483648时,由于我先转换成了abs(n),而正数n最大值为2147483647,因此报错。
第二个遇到的问题是,总是运行超时,一开始我写的pow()函数,是一般的循环算法,但是进行运行测试发现需要2700多ms,所以这种方法不行;
剑指offer中的公式
参考了剑指offer中的转换为递归的思路,
n为偶数,pow(8)=pow(4)*pow(4),pow(4)=pow(2)*pow(2),pow(2)=pow(1)*pow(1)
n为奇数,pow(9)=pow(4)*pow(4)*base,pow(4)=pow(2)*pow(2),pow(2)=pow(1)*pow(1)
在其编写的代码中,也了解到通过异常捕获,使程序鲁棒性更强,通过位运算,能实运行速度更加地快(B格也高了不少);
总之,学习了。
代码
class Solution {
public:
#define EPSILON 0.000001 //根据精度需要进行调整
bool g_InvalidInput = false;
double myPow(double x, int n) {
//基数为0且指数<0
if (fabs(x - 0.0) < EPSILON && n <= 0)
{
g_InvalidInput = true;
return 0.0;
}
//如果指数为负时,为临界值时,要特殊处理
if (n == -2147483648) {
return 1.0 / (x * Pow(x, abs(n + 1)));
}
else
{
int absN = abs(n);
//指数<0,返回其倒数
return n > 0 ? Pow(x, absN) : 1.0 / Pow(x, absN);
}
}
double Pow(double base, int e)
{
if (e == 0) return 1;
if (e == 1) return base;
//右移1位,相等于/2,位运算速度更快
double result = Pow(base, e >> 1);
result *= result;
//如果指数为奇数,根据公式,最后还要*base
//此处判断奇数,通过与1相与,速度更快
if (e & 0x1 == 1) result*= base;
return result;
}
};