快速幂算法

问题——如何求x^n(注: n为整数,x和n不可同时为零)

力扣(50题)

分析:首先讨论可能出现的几种情况

1.x==0&&n<=0,这种情况我们抛异常(math error)

2.x!=0&&n==0,结果为1

3.x==0&&n>0,结果为0

4.其他情况我们正常计算

分析完了,代码如下

    public double power(double x,int n){
        //这个合法判断应该放在这个函数
        if(x==0&&n<=0){
            throw new RuntimeException("math error!");
        }
        //这里需要用一个long类型变量,因为int类型最小的数的绝对值比最大值要大1
        long num=n;
        return num>=0? myPower(x,num):(1.0/myPower(x,-num));
    }
    
    //保证n为非负整数
    private double myPower(double x,long n){
        if(n==0){
            return 1.0;
        }
        double ans=1.0;
        while(n>0){
            ans=ans*x;
            n--;
        }
        return ans;
    }

这种朴素的求幂方法o(n)在n的规模很大时会time out!

分治法

        显然数学上而言,x^n=x^(n/2)*x^(n/2)

举个例子,例如我们要求3^65,朴素的算法要计算65次乘法运算,而用上面的的公式分解显然会有3^{65}=3^{32}*3^{32}*3,而3^{32}=3^{16}*3^{16}不断划分下去,很快就能降到

3=1*1*3,对于指数为n的只要进行logn次乘法

代码实现

public double powerByRecursion(double x,long n){
        //这个判断应该在n==0上面
        if(x==0&&n>0){
            return 0.0;
        }
        if(n==0){
            return 1.0;
        }
        //直观的查看递归了多少次
        System.out.println("函数执行了");
        double ans=powerByRecursion(x,n>>1);
        return (n&1)==1? ans*ans*x:ans*ans;
    }

运行效果如下

 

使用double来存储计算幂显然不够用,不过可以看到执行效率大大提高了

以下补充快速幂算法的迭代版本

public double quickPower(double x,long n){
        if(n==0){
            return 1.0;
        }
        double ans=1.0;
        while(n>0){
            //如果当前位不为0
            if((n&1)==1){
                ans=ans*x;
            }
            //自乘表示取对应位的值,为下一次循环准备
            x=x*x;
            n=n>>1;
        }
        return ans;
    }

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值