题目原文要求(摘抄自LeetCode):
Implement pow(x, n).
今天的题目比较简单,就是自己动手写一个乘方函数pow(x,n)。题目虽然简单,但是一次考虑全面还真的不是那么容易,你需要考虑很多临界条件。
我的解题思路:
记得同学第一次问我这个题目的时候,我就说:这个题目很简单,直接一个for循环就可以搞定了。我同学就鄙夷的笑了起来:你给我实现了看看,OJ系统肯定过不了的,绝对会超时的。也许是因为被小瞧了,我当时就考下海口:我一定只用for循环实现!可是虽然我最终用for循环实现了,也通过了OJ测试,但是这个过程真是太痛苦了。我最终的代码如下:
class Solution {
public:
double pow(double x, int n) {
if (n == 0)
{
return 1;
}
if (x == 1)
{
return 1;
}
else if (x == -1)
{
if (n %2 == 0)
{
return 1;
}
else
{
return -1;
}
}
double power = 1.0;
if (n > 0)
{
for (int i = 0; i < n; i++)
{
if (abs(power) < 1e-16)
{
return 0;
}
power *= x;
}
}
else
{
for (int i = 0; i < -n; i++)
{
if (abs(power) < 1e-16)
{
return 0;
}
power /= x;
}
}
return power;
}
};
难点分析(几个临界点需要特别注意):
1. 任何数的0次方都等于1;
2. 1的任何次方都等于1,不处理会给出超时错误;
3. -1的奇数次方等于-1,偶数次方等于1,不处理同样会给出超时错误;
4. 一个数的负数次方和正数次方的计算方法不一样,一定要分开处理,如果不处理负数的话,会给出如下错误:
5. 一定要在恰当的时候结束循环,当超出一定的精度时结束循环,我在这里取的是:1e-16,即当绝对值小于10的-16次方时,停止循环,结果输出为:0。当然你也可以取其他的精度,你也无需怀疑这是否正确,实质上:C++的函数pow(x,n)也是这样做的,你测试一下这个函数就会发现这个事实。如果不处理,会给出以下错误(超时):
结果展示:
经过上面的分析,最终笔者的算法在线测试也通过了,最后的结果如下:
大家可以看到,我虽然实现通过了可是时间还是比较长的。
其他实现途径:
另一种实现思路就是,采用递归的算法,首先计算x的2/n次方,然后x *= x即可得出结果,代码如下:
class Solution {
public:
double pow(double x, int n) {
if (n == 0)
return 1;
if (x == 1)
return 1;
if (x == -1)
{
if (n %2 == 0)
return 1;
else
return -1;
}
double power = 1.0;
if (n < 0)
power = 1 / pow(x, -(n/2));
else
power = pow(x, n/2);
if (n % 2 == 0)
return power * power;
else
{
if (n > 0)
{
return power * power * x;
}
else
{
return power * power / x;
}
}
}
};
我们可以从运行结果中看出这种方法的性能提高了4倍多,时间缩短到了36s,截图如下:
当然还有许多其他的优秀解法,有兴趣的可以继续探讨,而从本文我们也可以看出,没有最好的算法,只有更好的算法。
Python解决方案:
学习过python的人相比都知道,在python中有专门的乘方操作符**,如:2**5,表示2的5次方,因此用python来实现这个算法,相当简单,只需一行代码,即可。虽然时间有193ms,但是无疑是一个简单的解决方案。解决方案代码如下:
class Solution:
def pow(self, x, n):
return x**n