Pow(x,n)
关于一道计算x的n次幂的问题,如果采用累乘的形式,那就是最朴素的,最简单的一种求解方式,但不实用,累乘的算法的时间复杂度是O(n)。但是我们可以使用快速幂算法降低时间复杂度,将时间复杂度降低到O(logn),其中n是幂。
快速幂:
快速幂的做法简单来说就是把原来的幂拆成多个2的x次幂相加,比如511就拆成5(1+2+8),其中(1+2+8)是 20+21+23,怎么得出这一串的呢?就是把11次幂写成二进制就是:1011,然后1011换算成十进制的过程就是上面那一串~
所以原来要累乘11次的结果现在只需要累乘3次,分别乘51、52、58,可能有人会困惑,那么58也要累乘啊!有啥区别,所以在计算的过程就有技巧了;
以Pow(x,n)为例:先初始一个变量ans=1.0,然后用一个变量base保存x,然后根据n的二进制的位数,循环执行该位数次数的⊙base *= base,并且不断将n向右移位1位,直到n=0,这么得下来,base将会是x2、x4、x8、x16……,然后在执行⊙之前也要进行判断,如果n&1!=0,也就是说n的最右边一位是1,那意味需要把base累乘进ans,如果是0,那就不做操作,继续base *= base。
所以如果按511来测试:ans=1.0 、base=5、 n=11 =》1011
开始循环,退出条件是n=0
先判断 n最右一位是不是1 ,如果是,执行ans *= base 否则不执行
然后执行base *=base //累乘base
最后将n向右移位1位 //1011 =》0101
直到退出循环~
然后ans就是最终结果。所以ans只累乘了3次~
以下是代码实现,其中涉及的n可能是负数的情况!
func myPow(x float64, n int) float64 {
if n == 0 || x == 1.0{
return 1.0
}
var ans float64 = 1.0
var base float64 = x
b := n
if n < 0{
b *= -1
}
for b != 0{
if b & 1 != 0{
ans *= base
}
base *= base
b >>= 1
}
if n < 0{
return 1.0/ans
}
return ans
}
要坚持每天学习喔~