剑指Offer-14-打印1到最大的n位数

题目

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

解析

预备知识

因为题目没有说数据位数范围,所以这里应该为大数问题(即数的表示方式已超出编程语言自带的数据结构表示范围),需要自定义数据结构来表示大数。一般有2种方式表示大数:
1. 用字符数组,char[]来表示大数,其中数组每一个元素对应数中的每一位
2. 用字符串来表示大数,字符串中的每一位表示数的每一位

思路一

由于题目给定了数的位数,所以此处用字符数组比较方便。之后我们就对每个数进行自增操作即可,每自增一次就打印一次即可。直到数的位数大于n位。那么如何更快判断当前的数已经超出n位了呢?
1. 可以根据给定n,构造出n位最大的字符串,然后每次循环都与该字符串比较是否相等即可。比如输入5,那么每次自增完与99999判断是否相等来决定是否结束打印即可。字符串比较相等的复杂度为O(n)
2. 我们可以发现超出n位的最小的数最高位为1,这样我们可以判断char[0] 是否等于 ‘1’来判断是否超出了n位最大数,复杂度为O(1)

    public static void printToMaxOfNDigits1(int n) {
        if(n <= 0) {
            return;
        }
        char[] nums = new char[n + 1];
        Arrays.fill(nums, '0');
        while(!increment(nums)) {
            printNum(nums);
        }
    }

    /**
     * 大数自增操作!
     * 并判断是否已经超出了n位了。
     * @param nums
     * @return
     */
    public static boolean increment(char[] nums) {
        int carry = 0;
        for(int i = nums.length - 1; i >= 0; i--) {
            int temp = nums[i] - '0' + carry;
            //因为是加1,所以肯定是在最后一位上加1了
            if(i == nums.length - 1) {
                temp++;
            }
            carry = temp / 10;
            temp %= 10;
            nums[i] = (char)(temp + '0');
        }
        return nums[0] == '1';
    }

    public static void printNum(char[] nums) {
        int index = 0;
        for(; index < nums.length; index++) {
            if(nums[index] != '0'){
                break;
            }
        }
        for(; index < nums.length; index++) {
            System.out.print(nums[index]);
        }
        System.out.println();
    }

思路二

我们发现数的每一位都是0到9,所以可以利用全排列的思想,凭借递归的优雅实现达到目的。比如输入3,我们数的打印顺序为:

001
002

010
011
012

100
101

999
我们从高位开始,对于每一位都递归的用0-9填充,最后递归结束条件为已考察到所有的位,打印并且回溯到最后一位,重新对该位赋予下一个值。

    public static void printToMaxOfNDigits2(int n) {
        if(n <= 0) {
            return;
        }
        char[] nums = new char[n];
        recursiveProductNum(0, n, nums);
    }

    public static void recursiveProductNum(int index, int length, char[] nums) {
        if(index == length) {
            printNum(nums);
            return;
        }
        for(char i = '0'; i <= '9'; i++){
            nums[index] = i;
            recursiveProductNum(index + 1, length, nums);
        }
    }

    public static void printNum(char[] nums) {
        int index = 0;
        for(; index < nums.length; index++) {
            if(nums[index] != '0'){
                break;
            }
        }
        for(; index < nums.length; index++) {
            System.out.print(nums[index]);
        }
        System.out.println();
    }

你可能感兴趣的:(不刷题心里难受,剑指Offer)