剑指 Offer 16. 数值的整数次方
分析
这题看似简单,用模拟法就能搞定,但用模拟法会超时。即用O(n)的办法会超时。
按照一个正统的CS学生来说,用动态规划法更符合从技术上解决问题。
快速幂法更数学一些。
- 模拟法 - O(n)
- 快速幂 - O(logn)
- 动态规划 - O(logn)
且题目中说的n是整数,即可能是负数,所以要处理一下。动态规划法其实就是记忆化递归法。
模拟法
class Solution:
def myPow(self, x: float, n: int) -> float:
if x == 0: return 0
if n == 0: return 1
if n < 0: x, n = 1/x, -n
res = 1
for i in range(n):
res *= x
return res
快速幂法
快速幂的原理是,x5 = (x2)2*x. 其实就相当于动态规划法的逆过程了。
class Solution:
def myPow(self, x: float, n: int) -> float:
if x == 0: return 0
if n == 0: return 1
if n < 0: x, n = 1/x, -n
res = 1
while n:
# 等效于n%2, 效率更高
if n&1: res *= x
x *= x
# 等效于n//=2
n >>= 1
return res
动态规划法
class Solution:
def myPow(self, x: float, n: int) -> float:
if x == 0: return 0
if n == 0: return 1
# 这样做的目的是归一化处理
if n < 0: x, n = 1/x, -n
self.mem = dict()
self.mem[0] = 1
self.mem[1] = x
return self.pow_handler(x, n)
def pow_handler(self, x, n):
if n in self.mem:
return self.mem[n]
self.mem[n] = self.pow_handler(x, n//2) * self.pow_handler(x, n//2) * (x if n%2 else 1)
return self.mem[n]