这是我参与2022首次更文挑战的第11天,活动详情查看:2022首次更文挑战
数值的整数次方
实现 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/22 = 1/4 = 0.25
提示:
-100.0 < x < 100.0
-231 <= n <= 231-1
-104 <= xn <= 104
题解
算法一:快速幂(Java)
比如要求x^11,正常的乘积需要循环乘11次,时间复杂度为O(n)
快速幂的思想就是将指数11 可以转成二进制数1011,则原来的式子可以转化成
x^{11} = x^{2^{3} + 2^{1} + 2^{0}} = x^{2^{3}} * x^{2^{1}} * x^{2^{0}},此时只运算了3次乘积,时间复杂度降至O(logn)
下方代码中的x *= x是一个累乘的过程,得到四位二进制数,对应的四个权重,x,x *= x,x^2 *= x^2, x^4 *= x^4
1011二进制数,从右至左分别为1 1 0 1 ,只有在1的位置上,才有相应的权重,这也就是为什么需要通过与运算:(b & 1) == 1判断最后一位是否为1。
x ---> x^{2^{0}}x---------> 1
x^2 ---> x^{2^{1}}x-------------> 1
x^4 ---> x^{2^{2}}x-----------------> 0
x^8 ---> x^{2^{3}}x-----------------------> 1
最终的结果就是将每一位的1 所对应的权重相乘即可:x^{2^{0}} * x^{2^{1}} * x^{2^{3}}
class Solution {
public double myPow(double x, int n) {
if(n == 0) {
return 1;
}
long b = n;
if(b < 0) {
x = 1 / x;
b = -b;
}
double res = 1;
while(b > 0) {
if((b & 1) == 1) {
res *= x;
}
x *= x;
b >>= 1;
}
return res;
}
}
时间复杂度:O(log2N)
空间复杂度:O(1)
算法一:快速幂(Go)
思路同上
func myPow(x float64, n int) float64 {
if n == 0 {
return 1.0
}else if n <0 {
return 1.0 / myPow(x,-n)
}
temp:= myPow(x,n/2)
if n%2 ==0 { return temp *temp }
return x *temp *temp
}
时间复杂度:O(log2N)
空间复杂度:O(1)