leetcode 打印从1到最大的n位数(每日计划)

107 阅读1分钟

输入数字 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)