这是我参与8月更文挑战的第22天,活动详情查看:8月更文挑战
数值的整数次方
剑指Offer 16.数值的整数次方
实现pow(x,n)
,即计算x的n次幂函数(即x^n)。不得使用库函数,同时不需要考虑大数问题。
示例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
题解
法一 递归
使用递归的方法:
- 当n=0时,任何x都返回1
- 当n=1时,返回x
- 当n=-1时,返回1/x
对于其他n值:
- 当n为偶数时,myPow(x,n) = myPow(x,n/2)*myPow(x,n/2)
- 当n为奇数时,myPow(x,n) = myPow(x,(n-1)/2)*myPow(x,(n-1)/2) * x
注意:递归时先用一个变量取得myPow(x,n/2)的值再平方,可以降低时间复杂度(减少递归调用的次数)
/**
* @param {number} x
* @param {number} n
* @return {number}
*/
var myPow = function(x,n){
if(n===0) return 1;
if(n===1) return x;
if(n===-1) return 1/x;
if(n%2===0){
let a = myPow(x,n/2);
return a*a;
}
else{
let b = myPow(x,(n-1)/2);
return b*b*x;
}
}
法二 快速幂
假设x=3,n=5。那么5的二进制是:101。所以,3的5次方可以写成下图:
对x进行自乘,导致x的指数每次都扩大2倍。与n的二进制相对应。
以上图为例,整个算法的流程如下:
- 结果值result初始为1
- x初始为3,此时n的二进制最右位为1,更新结果为:x * n
- n右移一位。x进行累乘,x更新为3的2次方。由于n的二进制最右位为0,不更新结果
- n右移一位。x进行累乘,x更新为3的4次方。此时n的二进制最右位为1,更新结果为:x * result
- 结束
/**
* @param {number} x
* @param {number} n
* @return {number}
*/
var myPow = function(x, n) {
let reusult = 1.0;
//如果负数,2^-2可以变成(1/2)^2
if(n<0){
//js中默认不是整除
x = 1/x;
n = -n;
}
while(n>0){
if(n&1){ // 如果n最右位是1,将当前x累乘到result
reusult*=x;
}
x*=x; // x自乘法
//>>是有符号数的移位,>>>是无符号数的移位
//下面第一种是错误的,剩下两个都是正确的
// n = n>>1
// n = Math.floor(n/2)
n = n>>>1
}
return reusult;
};
打印从1到最大的n位数
剑指Offer 17.打印从1到最大的n位数
输入数字n,按顺序打印出从1到最大的n位十进制数。比如输入3,则打印出1、2、3一直到最大的3位数999.
示例1:
输入: n = 1
输出: [1,2,3,4,5,6,7,8,9]
说明:
- 用返回一个整数列表来代替打印
- n为正整数
题解
使用内置函数即可,可以使用快速幂来优化。
/**
* @param {number} n
* @return {number[]}
*/
var printNumbers = function(n){
let max = ''
while(n--) max += '9'
return new Array(max - '0').fill(0).map((val,index) => index + 1)
}
或
var printNumbers = function(n) {
let len = Math.pow(10, n)-1
return Array.from({length: len}, (item, index) => index+1)
};
坚持每日一练!前端小萌新一枚,希望能点个赞
哇~