返回

【详解】力扣 50 题:Pow(x, n) 两种解法,从零到精通

见解分享

破解「力扣」第 50 题:Pow(x, n) 的算法迷阵

序言

算法爱好者们,欢迎踏上「力扣」第 50 题:Pow(x, n) 的解题之旅。本题旨在检验我们的数学根基和算法技巧,我们将携手深入剖析「自顶向下」和「自底向上」两种解法,从零基础直达精通!

自顶向下:递归分治的利器

想象一下 ,你手中握着一柄分治之剑,将庞大难题层层分解,直至寻得问题的核心。这就是「自顶向下」递归解法的精髓。

  1. 递归终止条件: 当指数 n 为 0 时,问题迎刃而解,答案就是 1,因为任何数的 0 次方都等于 1。
  2. 奇偶性判断: 如果 n 是奇数,我们让 x 与自身递归求得的 x^(n-1) 携手相乘。
  3. 偶数情况: 如果 n 是偶数,我们递归求得 x^(n/2),然后将其平方,轻松得到 x^n。

代码示例:

def myPow1(x: float, n: int) -> float:
    if n == 0:
        return 1
    if n < 0:
        return 1 / myPow1(x, -n)
    if n % 2 == 0:
        return myPow1(x * x, n / 2)
    else:
        return x * myPow1(x, n - 1)

自底向上:二进制分解的妙招

不妨设想 ,指数 n 化身为一座迷宫,而二进制分解则化作一盏指路明灯,带领我们逐层探索。

  1. 指数分解: 我们将 n 二进制分解为 n1, n2, ..., nk,就像解开迷宫的层层机关。
  2. 循环求幂: 从最低位开始,我们依次计算 x^n1, x^(n1 + n2), ..., x^n,就像在迷宫中踏实前行。
  3. 乘法累积: 每次循环的结果与前一次相乘,就像在迷宫中不断累积前进的距离,最终抵达目标。

代码示例:

def myPow2(x: float, n: int) -> float:
    if n == 0:
        return 1
    if n < 0:
        x = 1 / x
        n = -n
    result = 1
    while n > 0:
        if n % 2 == 1:
            result *= x
        x *= x
        n = n // 2
    return result

时间和空间复杂度:深入探究

「自顶向下」递归解法:

  • 时间复杂度:O(log n)
  • 空间复杂度:O(log n)

「自底向上」二进制分解解法:

  • 时间复杂度:O(log n)
  • 空间复杂度:O(1)

总结:两种解法的取舍之道

「自顶向下」和「自底向上」各擅胜场,在不同的场景下展现出不同的优势:

  • 「自顶向下」更适用于问题分解明确、递归关系清晰的情形。
  • 「自底向上」则更适合问题层层递进、计算步骤确定的场景。

常见问题解答

1. 这两种解法中哪一种更好?

没有一刀切的答案,具体取决于问题和算法实现的细节。

2. 递归解法会不会陷入死循环?

只要递归终止条件正确,就不会陷入死循环。

3. 二进制分解解法在 n 为负数时如何处理?

将 x 取倒数,n 取绝对值,这样可以得到 x^(-n)。

4. 这两种解法对浮点数 x 的处理有什么不同?

「自顶向下」解法需要额外考虑浮点数溢出问题,而「自底向上」解法则通过循环实现浮点数的近似计算。

5. 这两种解法适用于哪些实际场景?

Pow(x, n) 函数在密码学、图像处理和科学计算等领域有着广泛的应用。