输入数字 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 len = 1;
let arr = [];
for (let i = 0; i < n; i ++) len *= 10;
for (let j = 0; j < len - 1; j ++) arr.push(j + 1)
return arr;
};
// 可以直接使用 Math.pow 函数来得到 len
/*
*var printNumbers = function(n) {
* let len = Math.pow(10, n);
* let arr = [];
* for (let j = 0; j < len - 1; j ++) arr.push(j + 1)
* return arr;
*};
**/
在写这个的时候我想到了如果数太大超过了整数的范围怎么办,但我看到返回的类型是整型数组,表示无能无力。
如果只打印,并没有类型要求,那么这个题就需要考虑。推荐使用字符串来表示,其他的什么类型都会存在越界的风险。这个周会补全这种情况。
换了一种方式,也就是在一个循环里面完成,只不过要做到这一点就需要每一次都比较一下:
/**
* @param {number} n
* @return {number[]}
*/
var printNumbers = function(n) {
let arr = [];
for (let i = 0, j = 1, len = 10; i < len - 1; i ++) {
arr.push(i + 1)
if (i === len - 2 && j < n) {
j ++;
len *= 10
}
}
return arr;
};
这两个,第一个要优于第二个,相对来说第一个做的“无用功”更少。
经过我的思考,我认为如果最后的个数也会出现溢出的话,那么数组的下标也有可能出现溢出,所以我使用的下面的方式:
// 先写一个字符串加法的函数,专门负责整数和整数之间的加法运算,也就是 “0” + “1” = “1”; “9” + “1” = “10” 类似于这样的加法函数。
function add(str1, str2) {
let a = 0;
let str = "";
for (let i = str1.length - 1, j = str2.length - 1; i >= 0 || j >= 0; i--, j--) {
let sum = 0;
if (str1[i]) {
sum += parseInt(str1[i]);
}
if (str2[j]) {
sum += parseInt(str2[j]);
}
sum += a;
a = Math.floor(sum / 10);
str = (sum % 10) + str;
}
if (a === 1) {
str = "1" + str;
}
return str;
}
// 因为上面的情况,我把数组的下标也保存成字符串,这样就肯定安全了,只不过如果数组的下标是字符串,就相当于这个数组是一个对象了。所以真正的安全是保存成一个对象。
/**
* @param {number} n
* @return {number[]}
*/
var printNumbers = function (n) {
let len = "1";
let arr = [];
for (let i = 0; i < n; i++) len += "0";
for (let j = "0"; add(j, "1") !== len; j = add(j, "1")) {
arr[j] = add(j, "1");
}
return arr;
};
来源:力扣(LeetCode)