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










