
题目分析
- 这道题我们采用分治思想来解决,对于求解xn我们可以先求出xn/2然后相乘得到xn。以此类推xn=(xn/2)2=((xn/4)2)2=...,这是n为偶数的情况,如果n为奇数我们需要对xn/2再乘以x,还要考虑一些特殊值以及数字越界的情况。
递归(代码)
var myPow = function(x, n) {
if (x === 0) return 0;
if (x === 1 || n === 0) return 1;
const logic = (b, i) => {
if (i === 1) return b;
return logic(b, i >>> 1) ** 2 * (i & 1 ? b : 1);
}
return n < 0 ? 1 / logic(x, -n) : logic(x, n);
};
题解
- 函数入口处我们首先对一些特殊值进行处理之后直接返回,然后开始进行递归求值,递归的终止条件为i==1。
- 如果n为负数,我们应该返回1/logic(x,−n)的计算结果。
- 题目中−231<=n<=231−1,当n=−231时我们会向logic中传入231,这时如果我们使用有符号右移>>就会陷入死循环。在js中所有的位运算都会先把运算数转换成有符号32位整型,超过32位的整数会被截断,小数部分会被舍弃。这里231已经超过js有符号32位整型的最大表示数,所以无法得到正确的计算结果。
- 对于这种情况我们采用无符号右移>>>来解决,该操作符不会考虑符号位,左侧会直接用0进行填充。
迭代(代码)
var myPow = function (x, n) {
if (x === 0) return 0;
if (x === 1 || n === 0) return 1;
let result = 1;
if (n < 0) {
x = 1 / x;
n *= -1;
}
while (n !== 0) {
if (n & 1) {
result *= x;
}
n >>>= 1;
x *= x;
}
return result;
};
题解
- 首先还是进行特殊值的处理。
- 如果n<0我们需要计算的就是(1/x)−n。
- 循环的终止条件是n=0,需要注意的是当n为奇数是需要对result乘上一次x。
总结
- 迭代相对于递归的优势在于少了函数调用栈的开销,但是代码相对于递归没有那么清晰明了。