题目:
实现 pow(x, n) ,即计算 x 的 n 次幂函数。
示例:
输入:x = 2.00000, n = 10
输出:1024.00000
输入:x = 2.00000, n = -2
输出:0.25000
解释: 2 − 2 = 1 / ( 2 × 2 ) = 1 / 4 = 0.25 2^{-2} = 1/(2×2) = 1/4 = 0.25 2−2=1/(2×2)=1/4=0.25
思路:
方法1,常规操作,先判断特殊情况,再一个一个乘,如果是小于0就一个一个除,但是这样会执行出错的。
方法2,普通的递归,会超时。
这里就是先判断特殊情况,然后就返回当前幂除以2,调用原函数乘以剩下的部分同样调用原函数,直到幂次为1返回值,但是这样计算有很多重复的部分,每次都要调用两次原函数,比如计算某个值,计算很多次相同的结果。
方法3,优化递归。
减少重复的计算,并且每次只调用一次函数,这里先判断特殊情况,然后当为偶数时,比如为4的时候,就是调用x的平方的平方,然后再调用x的四次方的一次方,就可以返回x的四次方,这里是先计算x的平方,再计算x的四次方,如果是奇数,就先按照这个数减1的偶数计算,最后再乘以x,这样减少了重复,提高了运算效率。
方法4
用位运算的方法,将十进制数转化为二进制数,比如10写成1010,幂次就可以写成2的三次方加2的一次方,原来的x的十次方就可以转化为x的8次方(2的三次方)乘以x的2次方(2的1次方),就是我们在最终的计算公式中保留的是二进制数中是1的位置上结果,比如1010,从右往左,第一位是1,而且是最高位,保留2的三次方,第三位是1,保留2的一次方。代码思路是从右往左取的,最低位如果是1就是乘以2的0次方,就是保留x本身乘进最后的结果里。
class Solution(object):
def myPow(self, x, n):
"""
:type x: float
:type n: int
:rtype: float
"""
# ans = 1
# if n == 0:
# return ans
# for i in range(abs(n)):
# if n < 0:
# ans /= x
# if n > 0:
# ans *= x
# return ans
#常规操作,执行出错,嗯嗯嗯
# 普通递归,会超出时间限制,因为这个过程里每一次递归都要调用两次函数,并且两个函数中有很多重复计算,比如计算x的5次方,中间计算好几次x的平方,x的一次方。
# if n == 0:
# return 1
# if n == 1:
# return x
# if n < 0:
# return 1/self.myPow(x,-n)
# return self.myPow(x,n//2) * self.myPow(x,n-n//2)
# 优化递归,如果减少重复的运算,并且每一次递归只调用一次函数
# if n == 0:
# return 1
# if n == 1:
# return x
# if n < 0:
# return 1/self.myPow(x,-n)#先按照正的计算,再取其倒数即可
# return self.myPow(x * x,n//2) if n%2 == 0 else x * self.myPow(x,n-1)
# 这样就终于AC了
#不用递归的方法,用位运算的方法
# if n == 0:
# return 1
# if n == 1:
# return x
# 以上两种情况都包括了
if n < 0:
return 1/self.myPow(x,-n)
res = 1
x_o = x
while n > 0:
if n % 2 == 1:#取当前的最低位
res = res * x_o
x_o *= x_o#不断更新,当前位置为1时,要乘以的x的次幂,分别是x的1次方,x的2,x的4,x的8次方等等,直到跳出循环
n //= 2#地板除,十进制转二进制的过程
return res