劍指offer面試題12 列印1到最大的n位數

頭像是我偶像發表於2017-06-29

一、題目

輸入數字n,按順序列印出從1到最大的n位十進位制數。比如輸入3,就列印出1、2、3、一起到最大的3位數,即999。

二、思考與分析

這個題目看似簡單,但是當輸入的n很大時,求最大的n位數用整型或長整型都會溢位。這裡需要考慮大數問題。

三、實現

方法一:在字串上模擬數字加法

用字串或者陣列來表示大數,首先我們把字串中的每個數字都初始化為’0’,然後每一次為字串表示的數字加1,再列印出來。因此我們只需要做兩件事情:
* 在字串表達的數字上模擬加法;
* 把字串表達的數字列印出來;

public class PrintNNum {
    public void print(int n) {
        if (n <= 0) {
            return;
        }
        char[] arr = new char[n + 1];
        for (int i = 0; i < arr.length; i++) {
            arr[i] = '0';
        }
        while (!imcrement(arr)) {
            printNum(arr);
        }
    }
    //在字串表示的數字上加1
    private boolean imcrement(char[] arr) {
        int len = arr.length - 1;
        while (arr[len] == '9') {// 從字元的最右邊開始,如果為‘9’就置‘0’,直到不是‘9’就將該位加1
            arr[len] = '0';
            len--;
        }
        arr[len] += 1;
        if (arr[0] == '1') {
            return true;
        }
        return false;
    }
    /*
     * 按照我們的閱讀習慣,將字串表示的數字列印出來
     * 即只有在碰到第一個非0的字元之後才開始列印,直到字串的結尾
     */
    private void printNum(char[] arr) {
        int isBegin0 = 0;
        for (int i = 0; i < arr.length; i++) {
            if (arr[i] == '0' && isBegin0 == 0) {
                continue;
            } else {
                isBegin0 = 1;
            }
            if (isBegin0 == 1) {
                System.out.print(arr[i]);
            }
        }
    }
}   

注意:

我們在建立陣列時,建立了n+1位的陣列,當加到最大的n位數時,即99…9時,再加1,就會在第一個字元(下標為0)的位置產生進位,當該位置產生進位時,則表示迴圈應該結束了。這樣也實現了用O(1)時間判斷是否已經到了最大的n位數。

方法二:將問題轉換成數字排列

我們把問題換個思路考慮,會發現n位所有十進位制數其實就是n個從0到9的全排列。也就是說,我們把數字的每一位都 從0到9排列一遍,就可以得到所有的十進位制數。只是在列印的時候,排在數字前面的0不列印出來而已。

全排列用遞迴很容易表達,數字的每一位都可能是0~9中的一個數,然後設定下一位,遞迴結束的條件是我們已經設定好了數字的最後一位。

//全排列實現列印
    private void printToMaxOfNDigits(int n){
        if(n <= 0){
            return;
        }
        char[] arr = new char[n];
        for (int i = 0; i < 10; i++) {
            arr[0] = (char) ('0'+i);
            printToMaxOfNDigitsRecursively(arr,n,0);
        }
    }

    private void printToMaxOfNDigitsRecursively(char[] arr, int n, int index) {
        if(index == n-1){
            printNum(arr);
            System.out.print("、");
            return;
        }
        for (int i = 0; i < 10; i++) {
            arr[index+1] = (char) (i+'0');
            printToMaxOfNDigitsRecursively(arr, n, index+1);
        }
    }

相關文章