0
点赞
收藏
分享

微信扫一扫

数值的整数次方(剑指offer 16)Java快速幂

驚鴻飛雪 2022-01-12 阅读 40

目录

一、题目描述

二、思路讲解

三、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) 

五、另一种方法 

        有迭代自然有递归。

举报

相关推荐

0 条评论