目录
一、题目描述
二、思路讲解
三、Java代码实现
四、时空复杂度分析
五、另一种方法
一、题目描述
实现 pow(x, n) ,即计算 x 的 n 次幂函数(即,xn)。不得使用库函数,同时不需要考虑大数问题。
示例 1:
输入:x = 2.00000, n = 10
输出:1024.00000
示例 2:
输入:x = 2.10000, n = 3
输出:9.26100
示例 3:
输入:x = 2.00000, n = -2
输出:0.25000
解释:2-2 = 1/22 = 1/4 = 0.25
提示:
-100.0 < x < 100.0
-231 <= n <= 231-1
-104 <= xn <= 104
二、思路讲解
首先先尝试了一下for循环暴力,超时。
然后试了一下两个头尾指针二分,超时。
然后就想到,可不可以让幂每次减半呢?(因为对于for循环来说,幂就代表着次数,幂减半,时间复杂度就可以降到logn了)。
当幂减半的时候,底数应该加倍。比如:2^10 = 4^5,原本需要遍历10次的,现在遍历5次就行了。
当然,这里也是要分奇偶性的:
1、当n为偶数时:x^n = x平方^(n/2);
2、当n为奇数时:x^n = x平方^(n/2) * x;(幂整除2之后,还要多乘一项)
我们就可以这样一直二分下去,当幂为0时,乘数就是我们要的结果了。举个例子:
2^10 = 4^5 = (4^2)^2 * 4 = (16^2)^1 * 4 = 1024^0 = 1024
三、Java代码实现
class Solution {
public double myPow(double x, int n) {
//当n为-2147483648时,n=-n会出现越界错误,所以用long
long nn = n;
boolean fu = false; //用来标记n是否为负数
if(nn == 0 || x==1.0){ //如果是0次幂或者底数为1(其实不需要判断,也可以通过)
return 1;
} else if(nn < 0){ //如果幂为负数
fu = true;
nn = -nn;
}
if(x == 0){ //如果底数为0
return 0;
}
double res = 1;
//将幂一直二分
while(nn > 0){
if(nn%2 != 0){
res = res * x;
}
//幂二分,底数就应该翻倍
x = x * x;
nn = nn / 2;
}
if(fu){ //如果是幂是负数,取倒数
res = 1 / res;
}
return res;
}
}
四、时空复杂度分析
时间复杂度: O(logn) n为幂
空间复杂度: O(1)
五、另一种方法
有迭代自然有递归。