返回

算法之美:探寻LeetCode 50 Pow(x, n)题的魅力

前端

LeetCode-50:Pow(x, n)

递归的力量

计算x的n次幂,自然而然地想到采用递归的方式,这也是解决该问题最直观的方法。递归的思路很简单:若n为奇数,则x的n次幂等于x的n-1次幂乘以x;若n为偶数,则x的n次幂等于x的n/2次幂的平方。递归的终止条件为n等于0,此时x的n次幂等于1。

    public double myPow(double x, int n) {
        if (n == 0) {
            return 1.0;
        }
        if (n < 0) {
            return 1.0 / myPow(x, -n);
        }
        if (n % 2 == 1) {
            return x * myPow(x, n - 1);
        }
        return myPow(x * x, n / 2);
    }

这种递归方法虽然简单易懂,但是存在一个致命的问题:时间复杂度太高。因为对于每个n,都需要计算x的n-1次幂,n-2次幂,依次类推,直到n为0。这样计算的复杂度是O(n),对于非常大的n,这种方法会非常耗时。

快速幂算法的登场

为了解决递归方法的时间复杂度过高的问题,我们引入快速幂算法。快速幂算法的核心思想是减少计算的次数,通过将n分解成二进制的形式,只计算必要的部分。具体来说,我们将n表示成二进制形式:

n = b_k * 2^k + b_{k-1} * 2^{k-1} + ... + b_1 * 2^1 + b_0 * 2^0

其中,b_k、b_{k-1}、...、b_1、b_0是0或1。然后,我们可以根据以下公式计算x的n次幂:

x^n = x^(b_k * 2^k + b_{k-1} * 2^{k-1} + ... + b_1 * 2^1 + b_0 * 2^0)
    = x^(b_k * 2^k) * x^(b_{k-1} * 2^{k-1}) * ... * x^(b_1 * 2^1) * x^(b_0 * 2^0)

我们发现,x^n可以表示为x的若干次幂的乘积,而这些次幂都是2的整数次幂。这样,我们就可以通过计算x的2的整数次幂,然后相乘,得到x^n的值。快速幂算法的时间复杂度是O(logn),大大降低了计算的次数。

    public double myPow(double x, int n) {
        if (n == 0) {
            return 1.0;
        }
        if (n < 0) {
            return 1.0 / myPow(x, -n);
        }
        double result = 1.0;
        while (n > 0) {
            if (n % 2 == 1) {
                result *= x;
            }
            x *= x;
            n /= 2;
        }
        return result;
    }

结语

在本文中,我们对LeetCode 50题Pow(x, n)进行了深入的探讨。我们从递归方法出发,分析了其时间复杂度过高的