实现函数double Power(double base, int exponent),求base的exponent次方。不得使用库函数,同时不需要考虑大数问题。
示例 1:
输入: 2.00000, 10
输出: 1024.00000
示例 2:输入: 2.10000, 3
输出: 9.26100
示例 3:输入: 2.00000, -2
输出: 0.25000
解释: 2-2 = 1/22 = 1/4 = 0.25说明:
- -100.0 < x < 100.0
- n 是 32 位有符号整数,其数值范围是 [−231, 231 − 1]
先用自带函数试一下:
class Solution:
def myPow(self, x: float, n: int) -> float:
return x**n
果然很高效
方法1 直接计算O(n)
思路
因为n是整数,故对n分情况讨论:
当n=0时,直接返回1即可;
当n>0时,则令x与x相乘(n-1)次即可;
当n<0时,则令1与x相除((-n)-1)次即可。
代码
class Solution:
def myPow(self, x: float, n: int) -> float:
power = 1
if x == 0:
if n != 0:
return 0
else:
return 1
if n==0:
return 1
elif n > 0:
for i in range(n):
power = power * x
return power
elif n < 0:
for i in range(-n):
power = power / x
return power
结果超出时间限制
在该算法中,时间复杂度为O(n).
方法2 二分法O(log2(n))
思路
有了上面的失败经验,这道题还是需要技巧的。
首先,n=0和n<0都可以转换为n>0,所以下面就针对n>0进行讨论:
如果像方法1那样计算x*x*x...*x是要计算n次的,所以复杂度为O(n);
如果能够改为计算(x^2)*(x^2)*(x^2)*(x^2)...*(x^2),则复杂度就会变成O(n/2);
如果能够利用分治思想,通过递归的方法,即每次都能将x的幂除以2,则复杂度就会成为log2(n)
具体代码如下
class Solution:
def myPow(self, x: float, n: int) -> float:
if n>0:
mod2 = n %2
if mod2 == 0:
npower2 = x*x
return self.myPow(npower2,n//2)
elif mod2 == 1:
npower2 = x*x
return self.myPow(npower2,n//2)*x
elif n<0:
n = -n
return 1 / self.myPow(x,n)
else:
return 1
结果
此时时间复杂度为O(log2(n)),不再超时。
方法3 "三分法"O(log3(n))
类似的我们还可以对其进行三分,每次迭代n都除以3,从而降低复杂度
class Solution:
def myPow(self, x: float, n: int) -> float:
if n>0:
mod3 = n %3
if mod3 == 0:
npower3 = x*x*x
return self.myPow(npower3,n//3)
elif mod3 == 1:
npower3 = x*x*x
return self.myPow(npower3,n//3)*x
elif mod3 == 2:
npower3 = x*x*x
return self.myPow(npower3,n//3)*x*x
elif n<0:
n = -n
return 1 / self.myPow(x,n)
else:
return 1
时间复杂度O(log3(n)),因此速度更快(其实只是理论速度更快,实际测试过程中并不一定)
总结
递归+分治的思想可以用来降低时间复杂度。