剑指 Offer 17. 打印从1到最大的n位数

260 阅读2分钟

题目

输入数字 n,按顺序打印出从 1 到最大的 n 位十进制数。比如输入 3,则打印出 1、2、3 一直到最大的 3 位数 999。

示例 1:

输入: n = 1
输出: [1,2,3,4,5,6,7,8,9]

 

说明:

  • 用返回一个整数列表来代替打印
  • n 为正整数

题解

如果可以在数字前面补0, 就会发现n位所有的十进制数其实就是 n个从 09的数字的全排列,也就是说,我们需要把数字的每一位都从09排列一遍,就得到所有的十进制数。只是在打印时,排在前面的0不打印出来。

以 n = 2 的全排列数字图示:

全排列.png

n=2的上根节点开始,每一条路径上的子节点的数字的字符,相加就是一个在[0, 99]的数字,除了第一条路径00不合法需要过滤调,通过递归就可以打印[0, 99]的所有数字。

全排列使用递归很容易,首先数字的每一位都可能是0-9中的任意一个数,设置好第一位,然后设置下一位,递归的终止条件是我们已经设置了数字的最后一位。

代码

**
 * @param {number} n
 * @return {number[]}
 */
var printNumbers = function(n) {
    const res = [];

    // 设置数字全排列的辅助数组,保存当前的数字
    const numbers = new Array(n).fill(0);
  
   
    
    // 遍历字符串中的第一位
    for (let i = 0; i < 10; i++) {
    
        numbers[0] = i.toString();
        _printNumbers(numbers, n, 0);
    }

    // 打印数字, 过滤开头为 0 的 数字 的字符串
    function printNumber(numbers) {
        let isBeginWithZero = true;
        let len = numbers.length;
          

        for (let i = 0; i < len; i++) {
            if (isBeginWithZero && numbers[i] != '0') {
                isBeginWithZero = false;
            }
            
        }

        if (!isBeginWithZero) {
            res.push(parseInt(numbers));       
        }
    }

    function _printNumbers(numbers, length, index) {
        // 递归结束条件是我们已经设置了数字的最后一位
        if (index == length - 1) {
            printNumber(numbers.join(''));
            return;
        }
        // 递归遍历第字符串的下一位
        for (let i = 0; i < 10; i++) {
            numbers[index + 1] = i.toString();
            _printNumbers(numbers, length, index + 1);
        }
    }

    return res;
};

原题链接

剑指 Offer 17. 打印从1到最大的n位数