一、题目描述
实现 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)
五、另一种方法
有迭代自然有递归。