审题
实现 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] 。
看到这道题的时候,我首先想到的是数值范围的问题,会不会还要自己实现长整数加减之类的问题…然而好像不用(用的话可真就麻烦了,长整型加减现在也不太会,以后有机会要好好实现一遍),因为double的范围还是很大的,并且测试数据也没有刻意难为我们,因此,专注于代码实现,我们实现了两种方法,暴力和分治,暴力就是纯的,一个一个乘,分治就是将例如:277变成238*238*2这种,那么思路清晰之后,我们直接看代码。
代码实现
方案一(上文提到的第一个方法(解决失败)):
这个方法想的很简单,分正负两种情况进行考虑,但是可惜的是只能过90%的测试数据,对于更多的测试数据不知道是因为精度不够还是什么原因,并不能够正确实现,还不是超时的问题。因为本身暴力就挺无聊的,我们不深究这个问题了,直接方案二。
class Solution {
public:
double neg(double x, int n) {
if ( n == 0 ) return 1;
else return neg(x, n+1)/x;
}
double pos(double x, int n) {
if ( x<1 && n>1000 ) return 0;
if ( n==1 ) return x;
else return x*pos(x, n-1);
}
double myPow(double x, int n) {
if ( n > 0 ) return pos(x, n);
else return neg(x, n);
}
};
方案2(分治):
看了官方题解,发现这个可以直接用一个函数进行实现,并且用了三目运算符之后的码风也是十分清晰,因此我们有了如下代码,其中需要注意两个地方:
- n不可以直接带入到我们自己的函数中,因为有一个-N的位置INT_MIN取负号是不可以用int表示的,因此要用到long long,不过这个是从C99才开始支持的概念,哎,既然官方题解都这么写了,那咱就也大胆用了。
- 对于分治,要判断是否需要多乘一个x和返回的条件。
掌握了这两点之后,我们有了如下代码。
class Solution {
public:
double quick(double x, long long n) {
if ( n == 0 ) return 1;
else {
double y = quick(x, n/2);
return (n%2) ? y*y*x : y*y;
}
}
double myPow(double x, int n) {
long long N = n;
return n>0 ? quick(x,N) : 1/quick(x,-N);
}
};
反思
对于这道题,在最开始想到了暴力解法就直接上手写了,然而,事实证明这是非常不好的一个行为,因为一是即使做出来对自己的码力也没有提高,毕竟这不是比赛,二是直接写没有优化自己的算法和抠细节,也失去了很多算法的简洁度,总而言之,想好再动笔永远是没错的,就像计算机上的空间换时间云云,我们不能用体力换脑力啊,毕竟我们还是要靠脑袋吃饭的,你说对吧。