刷题过程中遇到一个快速求幂的方法,特此记录
分治思想:
比如我们要计算x的y次方,通常情况我们需要执行y次。但是如果我们将其转化为(x*x) ^ (y/2)就只需要执行一半的时间了,那么如果是(x*x) * (x*x)) ^ (y/2/2)就只用四分之一的时间了,好。但这里有一个问题,你怎么知道y能一直被二整除呢?如果不能被整除怎么办?举个大家都会举的例子,计算3 ^ 10,第一次转化为了9 ^ 5 但下一次5/2不够除该怎么办?转化为(9^4)*(9^1),以下是递归写法。
def quick_pow(x, y):
if y == 0:
return 1
ret = quick_pow(x, y // 2)
return ret * ret if y % 2 == 0 else ret * ret * x
递归快速取模的算法思想没有问题,但是在递归的过程中,会使用很多额外的栈空间,是否存在一种办法,能通过迭代的循环方式完成,而非递归实现呢?答案当然是有的。我们只需要判断什么时候指数不能被2整除,则单独乘以底数,否则就将当前的数值平方即可。那么如何判断当前的指数是否能被2整除呢?
思路很简单:当一个数 & 1若为1,即该数的最后一位为1,不能被2整除,否则代表可以被2整数。
10: 00001010
1 : 00000001
按位与 00000000
------------------------
9: 00001001
1: 00000001
按位与 00000000
代码如下:
def quick_pow(x, y):
res = 1
while y:
if y & 1:
res *= x
x *= x
y = y >> 1
return res
虽然算法不难理解 但是比较精妙!新技能get!