一、题目描述
实现 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 n≥0 的范围内,即执行 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):res
、b
等变量占用常数大小额外空间
注意: 代码中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;
}
运行,测试通过