leetcode50:Pow(x, n)详解——py&go

leetcode50:https://leetcode-cn.com/problems/powx-n/
解题思路:
x n x^{n} xn 最简单的方法是通过循环将 n n n x x x 乘起来, 依次求 x 1 , x 2 , … , x n − 1 , x n , x^{1}, x^{2}, \ldots, x^{n-1}, x^{n}, x1,x2,,xn1,xn, 时间复杂度为 O ( n ) O(n) O(n)

快速幂方法可将时间复杂度降低至 O(log n),以下从“二分法”和“二进制”两个角度解析快速景法。

快速审解析(二进制角度):
利用十进制数字 n n n 的二进制表示,可对快速幂进行数学化解释。

  • 对于任何十进制正整数 n , n, n, 设其二进制为 " b m … b 3 b 2 b 1 " ( b i " b_{m} \ldots b_{3} b_{2} b_{1} "\left(b_{i}\right. "bmb3b2b1"(bi 为二进制某位值, i ∈ [ 1 , m ] ) , \left.i \in[1, m]\right), i[1,m]), 则有:
    • 二进制转十进制: n = 1 b 1 + 2 b 2 + 4 b 3 + … + 2 m − 1 b m \quad n=1 b_{1}+2 b_{2}+4 b_{3}+\ldots+2^{m-1} b_{m} \quad n=1b1+2b2+4b3++2m1bm (届一进制转十进制公式)
    • 幂的二进制展开: x n = x 1 b 1 + 2 b 2 + 4 b 3 + … + 2 m − 1 b m = x 1 b 1 x 2 b 2 x 4 b 3 … x 2 m − 1 b m \quad x^{n}=x^{1 b_{1}+2 b_{2}+4 b_{3}+\ldots+2^{m-1} b_{m}}=x^{1 b_{1}} x^{2 b_{2}} x^{4 b_{3}} \ldots x^{2^{m-1} b_{m}} xn=x1b1+2b2+4b3++2m1bm=x1b1x2b2x4b3x2m1bm
  • 根据以上推导, 可把计算 x n x^{n} xn 转化为解决以下两个问题:
    • 计算 x 1 , x 2 , x 4 , … , x 2 m − 1 x^{1}, x^{2}, x^{4}, \ldots, x^{2^{m-1}} x1,x2,x4,,x2m1 的值: 循环赋值操作 x = x 2 x=x^{2} x=x2 即可
    • 获取二进制各位 b 1 , b 2 , b 3 , … , b m b_{1}, b_{2}, b_{3}, \ldots, b_{m} b1,b2,b3,,bm 的值: \quad 循环执行以下操作即可。
    1. n & 1 n \& 1 \quad n&1 (与操作) : 判断 n n n 二进制最右一位是否为 1 ;
    2. n > > 1 n>>1 \quad n>>1 (移位操作) : n \quad n n 右移一位 (可理解为删除最后一位)
  • 因此, 应用以上操作, 可在循坏中依次计算 x 2 0 b 1 , x 2 1 b 2 , … , x 2 m − 1 b m x^{2^{0} b_{1}}, x^{2^{1} b_{2}}, \ldots, x^{2^{m-1} b_{m}} x20b1,x21b2,,x2m1bm 的值, 并将所有 x 2 i − 1 b i x^{2^{i-1} b_{i}} x2i1bi 累计相乘即可, 其中:
    x 2 i − 1 b i = { 1 , b i = 0 x 2 i − 1 , b i = 1 x^{2^{i-1} b_{i}}=\left\{\begin{array}{ll} 1 & , b_{i}=0 \\ x^{2^{i-1}} & , b_{i}=1 \end{array}\right. x2i1bi={1x2i1,bi=0,bi=1
    在这里插入图片描述
    快速审解析(分治法角度):
    快速绵实际上是分治思想的一种应用。
  • x n = x n / 2 × x n / 2 = ( x 2 ) n / 2 , x^{n}=x^{n / 2} \times x^{n / 2}=\left(x^{2}\right)^{n / 2}, xn=xn/2×xn/2=(x2)n/2, n / 2 n / 2 n/2 为整数, 则需要分为奇偶两种情况(设向下取整除法符号为 " / / " / / " //" ) :
    x n = { ( x 2 ) n / / 2 , n  头偶数  x ( x 2 ) n / / 2 , n  头奇数  x^{n}=\left\{\begin{array}{ll} \left(x^{2}\right)^{n / / 2} & , n \text { 头偶数 } \\ x\left(x^{2}\right)^{n / / 2} & , n \text { 头奇数 } \end{array}\right. xn={(x2)n//2x(x2)n//2,n 头偶数 ,n 头奇数 
    观察发现,当 n n n 为奇数时, 二分后会多出一项 x x x
  • 审结果获取
    • 根据推导, 可通过循环 x = x 2 x=x^{2} x=x2 操作, 每次把审从 n n n 降至 n / / 2 , n / / 2, n//2, 直至将审降为 0 ;
    • r e s = 1 , r e s=1, res=1, 则初始状态 x n = x n × r e s x^{n}=x^{n} \times r e s xn=xn×res 。在循环二分时, 每当 n n n 为奇数时, 将多出的一项 x x x 乘入 r e s , r e s, res, 则 最终可化至 x n = x 0 × r e s = r e s , x^{n}=x^{0} \times r e s=r e s, xn=x0×res=res, 返回 r e s r e s res 即可。
      在这里插入图片描述
  • 转化为位运算:
    • 向下整除 n / / 2 n / / 2 n//2 等价于 右移一位 n > > 1 n>>1 n>>1;
    • 取余数 n % 2 n \% 2 n%2 等价于 判断二进制最右位 n & 1 n \& 1 n&1;

算法流程:

  1. x = 0.0 x=0.0 x=0.0 时:直接返回 0.0 , 0.0 , 0.0 以避免后续 1 除以 0 操作报错。分析:数字 0 的正数次审恒为 0 ; 0 0 ; \quad 0 0;0 的 0 次审和负 数次审没有意义, 因此直接返回 0.0 即可。
  2. 初始化 r e s = 1 res = 1 res=1
  3. n < 0 n<0 n<0 时:把问题转化至 n ≥ 0 n \geq 0 n0 的范围内, 即执行 x = 1 / x , n = − n x=1 / x, n=-n x=1/x,n=n
  4. 循环计算: 当 n = 0 n=0 n=0 时跳出。
    1. n & 1 = 1 n \& 1=1 n&1=1 时: 将当前 x x x 乘入 res (即 res ⁡ ∗ = x ) \operatorname{res} *=x) res=x)
    2. 执行 x = x 2 ( x=x^{2} \quad( x=x2( x ∗ = x ) x *=x) x=x)
    3. 执行 n n n 右移一位 ( ( ( n > > = 1 ) n>>=1) n>>=1)
  5. 返回 res

复杂度分析:

  • 时间复杂度 O ( log ⁡ n ) : O(\log n): O(logn): 二分的时间复杂度为对数级别。
  • 空间复杂度 O ( 1 ) : r e s , b O(1): \quad r e s, b O(1):res,b 等变量占用常数大小额外空间。

PY

class Solution:
    def myPow(self, x: float, n: int) -> float:
        if x == 0.0: return 0.0
        res = 1
        if n < 0: x, n = 1 / x, -n
        while n:
            if n & 1: res *= x
            x *= x
            n >>= 1
        return res

GO

func myPow(x float64, n int) float64 {
    if x == 0.0 {
        return 0.0
    }
    res := 1.0
    if n < 0{
        x , n = 1/x , -n
    }
    for i := n ; i > 0; i>>=1 {
		//fmt.Println(i)
        if (i % 2 == 1){
			res *= x
        }
		x *= x
		//fmt.Println(x)
    }
    return res
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

浩波的笔记

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值