剑指Offer:[第20天 分治算法(中等)]--->数值的整数次方


一、题目描述

实现 pow(x, n) ,即计算 x 的 n 次幂函数(即,xn)。不得使用库函数,同时不需要考虑大数问题。

示例1:

输入:x = 2.00000, n = 10
输出:1024.00000

示例2:

输入:x = 2.10000, n = 3
输出:9.26100

示例3:

输入:x = 2.00000, n = -2
输出:0.25000
解释:2^(-2) = 1/(2^2) = 1/4 = 0.25

提示:

-100.0 < x < 100.0
-231 <= n <= 231-1
-104 <= xn <= 104


二、思路分析

注:思路分析中的一些内容和图片参考自力扣各位前辈的题解,感谢他们的无私奉献

思路

二分推导 x n = x n / 2 × x n / 2 = ( x 2 ) x n / 2 {x^n} = {x^{n/2}} \times {x^{n/2}} = ({x^2}){x^{n/2}} xn=xn/2×xn/2=(x2)xn/2,令 n / 2 n/2 n/2 为整数,则需要分为奇偶两种情况(设向下取整除法符号为//):
n n n 为偶数: x n = ( x 2 ) x n / 2 {x^n} = ({x^2}){x^{n/2}} xn=(x2)xn/2
n n n 为奇数: x n = x ( x 2 ) x n / 2 {x^n} = x({x^2}){x^{n/2}} xn=x(x2)xn/2
幂结果获取
根据二分推导,可通过循环 x = x 2 x = x^2 x=x2操作,每次把幂从 n n n 降至 n / / 2 n//2 n//2,直至将幂降为0
r e s = 1 res=1 res=1,则初始状态 x n = x n × r e s x^n = x^n \times res xn=xn×res。在循环二分时,每当 n n n 为奇数时,将多出的一项 x x x 乘入 r e s res res,则最终可化至 x n = x 0 × r e s x^n = x^0 \times res xn=x0×res,返回 r e s res 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
在这里插入图片描述
算法流程:
x = 0 x=0 x=0 时,直接返回0(避免后续 x = 1 / x x=1/x x=1/x 操作报错)
初始化 r e s = 1 res=1 res=1
n < 0 n<0 n<0 时,把问题转化至 n ≥ 0 n \geq 0 n0 的范围内,即执行 x = 1 / x x=1/x x=1/x n = − n n=−n n=n
循环计算:当 n = 0 n = 0 n=0 时跳出
----当 n & 1 = 1 n \& 1 = 1 n&1=1 时:将当前 x x x 乘入 r e s res res (即 r e s ∗ = x res *= x res=x)
----执行 x = x 2 x = x^2 x=x2,(即 x ∗ = x x *= x x=x)
----执行 n n n 右移一位,(即 n > > = 1 n >>= 1 n>>=1)
返回 r e s res res
复杂度分析:
时间复杂度 O ( l o g 2 N ) \rm{O(log_2N)} O(log2N):二分的时间复杂度为对数级别
空间复杂度 O ( 1 ) \rm{O(1)} O(1)resb等变量占用常数大小额外空间
注意: 代码中int32变量 n ∈ [ − 2147483648 , 2147483647 ] n \in [-2147483648, 2147483647] n[2147483648,2147483647],因此当 n = − 2147483648 n = -2147483648 n=2147483648 时执行 n = − n n = -n n=n 会因越界而赋值出错。解决方法是先将 n n n 存入 long 变量b,后面用b操作即可。


三、整体代码

整体代码如下

double myPow(double x, int n){
    if(x == 0) return 0;
    double res = 1.0;
    long b = n;
    if(b < 0) {
        b= -b;
        x = 1/x;
    }
    while(b>0){
        if((b&1)==1) res*=x;
        x*=x;
        b>>=1;
    }
    
    return res;
}

运行,测试通过
在这里插入图片描述

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

知初与修一

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

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

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

打赏作者

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

抵扣说明:

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

余额充值