剑指 Offer 16. 数值的整数次方

606 阅读1分钟

题目描述

实现 pow(x, n) ,即计算 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/2^2 = 1/4 = 0.25

提示:
-100.0 < x < 100.0
-231 <= n <= 231-1
-104 <= xn <= 104

解题思路1: 二分法 O(log2n)

x的n次幂, 我们可以看做是 x的 n/2次幂 乘 x的n/2 次幂, 然后就可以使用二分法进行计算下去, 这里我们依然使用一个map进行剪枝

示例代码1:

def myPow(x: float, n: int) -> float:
    def helper(x, n):
        if n == 0:
            return 1

        if n in visit:
            return visit[n]

        if n & 1 == 0:  # 如果n为偶数, 分治为  x ^ (n//2) * x ^ (n//2)
            res = helper(x, n // 2) * helper(x, n // 2)
            visit[n] = res
            return res
        else: # 如果n为偶数, 分治为 x * x ^ (n//2) * x ^ (n//2)
            res = x * helper(x, n // 2) * helper(x, n // 2)
            visit[n] = res
            return res

    # 添加map, 记录计算过的值进行剪枝
    visit = {}

    if n > 0:
        return helper(x, n) # 如果 n 的正负判断
    else:
        return 1 / helper(x, -n)

解题思路2: 数学法, 快速幂 O(n)

快速幂法的思路

示例代码2:

def myPow(x: float, n: int) -> float:
    if x == 0:
        return 0
    if n < 0:
        x, n = 1 / x, -n # 如果n小于0, 进行数据转换
    res = 1
    while n > 0:
        if n & 1 == 1:
            res *= x # 如果当前位是1, 进行权重相乘
        x *= x # 权重累积
        n >>= 1 # 将n左移进行下一次循环
    return res

同样, 快速幂的方法, 比二分法要高效很多

28ms为快速幂, 40ms为二分法