LeetCode琅琊榜第五层- Pow(x, n)(快速幂思想)

LeetCode_50.Pow(x, n)

难度:中等

博主空间+往期LeetCode

题目


目录

作者的原始思路

暴力求解

代码简述:

问题

官方解法-快速幂算法

题目分析

思路分析

代码实现

代码如何根据算法思想转化而来的?

结论


作者的原始思路

暴力求解

class Solution {
    public double myPow(double x, int n) {
        double res = 1;
        if (x == 1 || x == 0) {
            return x;
        }else if (x == -1) {
            return n%2 == 0? 1 : -1;
        }
        if (n < -100) {
            return 0;
        }
        if(n < 0) {
            while (n != 0) {
                res *= (1/x);
                n++;
            }
            return res;
        }else if (n == 0) {
            return 1;
        }else {
            while (n != 0) {
                res *= x;
                n--;
            }
        }
        return res;
    }
}

代码简述:

  • 先处理特殊情况,例如当x = 1或x = 0的情况,直接返回即可,没必要去算,当x = -1的时候我们只需要判断幂的奇偶性就可以判断出来答案,再考虑一个特殊情况,当n足够小的时候直接返回0即可

问题

  • 代码的效率太低,代码的时间复杂度是O(N)线性阶
  • 能否一个比线性阶还要低的时间复杂度,明显的是,我们可以用O(logN)对数阶来实现

官方解法-快速幂算法

题目分析

  • 题目要求我们计算X^n,即翻译过来就是"X1*X2*X3....*Xn"有n个X进行相乘,最后的结果就是题目想要的结果
  • 通过这里,我们仔细研究可以发现,这里有大量的重复的操作,即X*X*X....,我们需要对这些重复的操作做出对应的处理
  • 如果我们可以通过快速幂的算法来减少计算次数,从而优化算法

思路分析

  • 我们可以采用二分的思想(快速幂的前提)去解决该问题,即2^10 = 2^5 * 2^5,将该运算用二分的思想分开两半进行运算
  • 不断重复以上过程,直到分完为止
  • 显然这样的算法没有一个一个去算,而采用折半去算,大大减少了运算次数

代码实现

class Solution {
    public double myPow(double x, int n) {
        if (x == 1 || n == 0) {
            return 1;
        }
        var res = 0.0;
        if (n < 0) {
            res = 1/calculate1(x,-n);
        }else {
            res = calculate1(x,n);
        }
        return res;
    }

    public double quickMul(double x, long N) {
        if (N == 0) {
            return 1.0;
        }
        double y = quickMul(x, N / 2);
        return N % 2 == 0 ? y * y : y * y * x;
    }
}

代码如何根据算法思想转化而来的?

  • 1.根据算法思想,我们可以得出以下的表达式

  •  2.假设我们建立一个专门完成这件事的方法,其参数列表与返回值类型如下

  • 3.先看左半部分,作为调用者,我们希望最开始传递2与10进去
    • 如果我们传递(2,10),则就是1中的第一行与2^10对应
    • 这说明了下一次递归要传递(2,5) -> (2,2) -> (2,1)这些参数

  • 我们得出了这样一个递归代码 

  • 4.再看右半部分 
    • 我们发现,想要获得2^10的结果,我们需要两个2^5相乘
    • 进一步观察,我们发现,左边的次幂是奇数的时候,需要多一个2,即多一个x,当左边的次幂是偶数的时候,就不需要,我们可以得出以下代码

  • 5,最后再看整体部分
    • 我们发现n=1的时候,就算完了,所以而且值就等于2,所以我们得出以下代码

  • 6,代码汇总后,得到如下代码 

  • 7,代码的优化
    • 我们发现上面的代码即return calculate(x,n/2) * calculate(x,n/2);代码冗余了
    • 比如此刻n=10,x=2,两个方法传过去的都是5,结果一定是一样的,即代码冗余了
    • 代码冗余产生的后果是递归多了一半,效率大大降低,此刻我们需要做出以下的更改
    • 即我们只递归一次,将返回值类型用y接受
    • 再利用三目操作符完成以上的两个if
    • 这有效的减少了一半的递归 

结论

        快速幂的思想还是挺简单的,即用二分的思想就可以把算法的思想以及递推公式求解出来,但是,快速幂也不简单,不简单在怎么用递推公式推出算法思想,最后,总结一下最重要的几点

        1.递推公式的创建

        2.如何用递推公式得出代码

        3.快速幂的使用场景

  • 35
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 39
    评论
评论 39
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

爪哇土著、JOElib

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值