暴力求解直接乘以n
个n
的方式可行,但是显然不是我们需要的方案。
分治
n
为偶数的时候,x
的n
次方转为x
的n/2
的相乘,每个x
的n/2
次方可以继续转为x
的n/4
相乘....
n
为奇数的时候,n
次方转为n/2
(取整)之后,多出一个x
,再以相同的逻辑继续下分。
这样一来,乘法操作的次数被大大降低,时间复杂度被降到O(logn)
的级别。
var myPow = function (x, n) {
if (n === 0) {
return 1;
}
if (n < 0) {
return 1 / myPow(x, -n);
}
if (n % 2) {
return x * myPow(x, n - 1);
}
return myPow(x * x, n / 2);
};
分析:
n<0
的时候,取倒数转化成n
大0
的情况,继续递归n
为奇数的情况,提取一个x
出来,后面的myPow(x, n - 1)
指数n-1
就是偶数n
为偶数的情况,转为两个x
的n/2
次方相乘的形式- 一直递归,
n/2
一直划分,直到n=1
,递归终止将结果依次返回。
循环&位运算
对指数n
的降次可以通过位运算,通过&1
操作符即可判断奇偶
const newPow = (x, n) => {
if (n < 0) {
x = 1 / x;
n = -n;
}
let pow = 1;
while (n) {
if (n & 1) {
pow = pow * x;
}
x = x * x;
n >>= 1;
}
return pow;
};
没有通过递归和分治,而是从pow=1
开始循环累加的效果,偶数时,x=>x2,奇数时再把x
乘到pow
上,且,x=>x2。反推出来很巧妙。