「这是我参与2022首次更文挑战的第15天,活动详情查看:2022首次更文挑战」。
每日刷题第37天 2021.02.02
数值的整数次方
- leetcode原题链接:leetcode-cn.com/problems/sh…
- 难度:中等
- 方法:递归、快速幂、算数移位、逻辑移位
题目
- 实现 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-2^31 <= n <= 2^31-1-10^4 <= x^n <= 10^4
拓展
- 算数移位:最高位为符号位,存储有符号整型。
- 正数:最高位为0,计算机中存储正数用原码
- 负数:最高位为1,计算机中存储负数用补码(原码取反+1)
- 逻辑移位:没有符号位,存储无符号整型。
- 本题指数为负数时,有两种解决办法
- 将指数取绝对值变为正数,即:
n = -n,x不变,最后将返回:1/ans - 转换底数
x为1/x,n不变,最后返回ans
- 将指数取绝对值变为正数,即:
- 使用
JS中的>>运算符的时候存在一个坑点:>>算数移位,因为题目中给的数据,负数可以取到-2^31,但是将其转换为正数后,就会超出有符号整型的最大值2^31-1,那么js内部就会将其转换为无符号整数进行存储,这时就不会超出。but此时再使用>>算数移位运算符就会出错。>>>逻辑移位,解决方案,使用逻辑移位运算符即可。
解法
- 递归方法:
- n为奇数 -> (x^ 2/n)^2 * x
- n为偶数 -> (x^ 2/n)^2
- n = 0 -> 1 (递归的终止返回条件)
/**
* @param {number} x
* @param {number} n
* @return {number}
*/
var myPow = function(x, n) {
// 使用快速幂算法
// 递归的思想
// 1.奇数 a,n-1 * a
// 2.偶数 a, n / 2
// 3. a,0 1
function fastPower (x,n) {
if (n == 0) return 1;
n = n < 0 ? -n : n;
if (n % 2 == 0) {
// 偶数
let record = fastPower(x,n / 2);
return record * record;
}else {
// 奇数
return fastPower(x, n - 1) * x;
}
}
if (n < 0) {
// 指数是负数
return (1 / fastPower(x,n)).toFixed(5);
}else {
return fastPower(x,n).toFixed(5);
}
};
- 非递归方法:使用
while循环,计算机中存储的形式为二进制,因此可通过每次右移来判断是否需要累乘到ans中。- 为什么每一轮都要
x *= x,原因如下(举例x = 3, n = 13),n二进制'1101',下面将其反过来写,便于观察1 0 1 1 3 3*3=9 9*3=27 27*3=81 要 不要 要 要 - 由观察可知,不论为
1还是为0,X都需要累乘。
- 为什么每一轮都要
/**
* @param {number} x
* @param {number} n
* @return {number}
*/
var myPow = function(x, n) {
// 非递归做法的快速幂
if (x == 1 || n == 0) return 1;
if (n == 1) return x;
let ans = 1,flag = false;
n > 0 ? flag = true : n = -n;
while (n != 0) {
if (n & 1 != 0) ans *= x;
x *= x;
// 可替换
n >>>= 1;
// 替换语句
n = Math.floor(n / 2);
}
if (flag) return ans;
else return 1 / ans;
};
附录
- 移位运算符
>>>>> - 位运算符
&:可以判断当前的值的奇偶性 - 取固定小数位:
toFixed(5)