力扣第五十题-Pow(x, n)

598 阅读2分钟

这是我参与8月更文挑战的第17天,活动详情查看:8月更文挑战

前言

力扣第五十题 Pow(x, n) 如下所示:

实现 pow(xn) ,即计算 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

一、思路

这一题题目还是比较好理解的,就是实现一个 求n次幂的函数

我看到这题之后想的是使用递归来实现,但是当 N = 2147483647 很容易就栈溢出了。

伪代码如下所示(每次次方+1):

    public double myPow(double x, int n) {
        return n > 0 ? dfs(x, x, n) : 1/dfs(x, x, -n);
    }
    
    public double dfs(double x, double p, int n) {
        if (Math.abs(n) == 1)
            return x;
        return dfs(x * p, p,n-1);
    }

那么如何优化呢?怎么样可以有效的减少递归的层数呢?

答案是:分治算法

分治算法的思路就是将问题向下分解,如二分法

分治 + 递归 的大致的步骤如下所示:

  1. 如果当前层无法处理,就分解,并向下递归
  2. 如当前处理的次方为 1,则开始向上回溯

举个例子

此处以 x = 2.0, n = 10 作为例子

  1. 递归1:2的10次方 解决不了,向下分解为 n = 10/2 = 5
  2. 递归2:2的5次方 解决不了,向下分解为 n = 5/2 = 2
  3. 递归3:2的2次方 解决不了,向下分解为 n = 2/2 = 1
  4. 递归4:2的1次方 有解,向上回溯结果 2
  5. 递归3:向上回溯结果 2 * 2 = 4
  6. 递归2:向上回溯结果 4 * 4 * 2 = 32
  7. 递归1:向上回溯结果 32 * 32 = 1024
  8. 返回结果 1024 即可

综上所述,整个分解的过程为 n^10 -> n^5 -> n^2 -> n^1

二、实现

实现代码

实现代码与思路保持一致

    public double myPow(double x, int n) {
        // 特殊情况
        if (x == 0 || x == 1)
            return x;
        if (n == 0)
            return 1;
        return n > 0 ? quickMul(x, n) : 1/quickMul(x, -n);
    }

    public double quickMul(double x, long N) {
        if (Math.abs(N) == 1)   // 特殊情况:N可能会为-2147483648
            return x;
        double y = quickMul(x, N / 2);
        return N % 2 == 0 ? y * y : y * y * x;
    }

测试代码

    public static void main(String[] args) {
        double ret = new Number50().myPow(2.0, 10);
        System.out.println(ret);
    }

结果

image.png

三、总结

感谢看到最后,非常荣幸能够帮助到你~♥