剑指Offer对答如流系列 - 打印1到最大的n位数

Posted jefferychenxiao

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了剑指Offer对答如流系列 - 打印1到最大的n位数相关的知识,希望对你有一定的参考价值。

面试题16:打印1到最大的n位数

问题描述

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

问题分析

这种问题一看就很简单嘛,很多人不经过细致分析,上来一写,就错了。要是在面试中,犯了这种错误,会留下态度不严谨的印象。

n位数并未指明多少位,说明可能会有大数现象的存在,那个时候不能简单用int或者long数据输出。我们不得不考虑使用字符。

考虑到字符数组比字符串更加灵活,不妨以字符数组为切入点进行分析。我们最终的目标是通过字符数组char[]来进行输出数字。

比较容易想到的方式就是

  1. 采用递归将每一位都从0到9排列出来

  2. 把字符串表达的数字打印出来

不过有的朋友应该接触过 在字符串上模拟数字加法的面试题,这道题的详细可以用到这里

  1. 在字符串表达的数字上模拟加法;

  2. 把字符串表达的数字打印出来。

下面两种方式,都进行一下实现。

问题解答

方法一:

    public void printToMaxOfNDights1s(int n) {
        
        if(n<=0) {
            return;
        }
        char[] digit = new char[n];
        for(int i=0;i<n;i++) {
            digit[i]='0';
        }
        for(int i=n-1;i>=0;i--) {
            while(digit[i]!='9') {
                int m=0;
                digit[m]++;
                while(m<n-1 && digit[m]>'9') {
                    digit[m]='0';
                    digit[m+1]++;
                    m++;
                }
                printdigits(digit);
            }
        }
    }

    private void printdigits(char[] digit) {
        int m = digit.length-1;
        while(digit[m]=='0') {
            m--;
        }
        
        for(int i=m;i>=0;i--) {
            System.out.print(digit[i]);
        }
        System.out.println();
    }

方法二:

    public void printToMaxOfNDigits(int n) {
       
        if (n <= 0) {
            return;
        }
        char[] number = new char[n];
        // 不能用foreach方法对nuber[]赋值
        // for (char c : number) {
        // c = '0';
        // }
        for (int k = 0; k < number.length; k++) {
            number[k] = '0';
        }
        while (!increment(number)) {
            printCharNumber(number);
        }
    }

    /**
     * 对字符串进行加一操作,number达到最大值后返回true
     * 最低位加一;所有位如果超过10,则进位
     */
    private boolean increment(char[] number) {
        int nTakeOver = 0; // 代表进位
        for (int i = number.length - 1; i >= 0; i--) {
            int nSum = (number[i] - '0') + nTakeOver; // 当前位置数字
            // number[i]-'0'是把char转化为int,nTakeOver代表进位
            if (i == number.length - 1) {
                nSum++;
            }
            if (nSum >= 10) {
                if (i == 0) {
                    return true; // 超出范围了
                }
                nTakeOver = 1;
                nSum -= 10;
                number[i] = (char) (nSum + '0');
            } else {
                number[i] = (char) (nSum + '0');
                break; // 高位不变,可以直接跳出循环了
            }
        }
        return false;
    }

    /**
     * 打印字符数组形成的数字
     * 书中方法:利用布尔变量isBeginning0来从第一个非零字符打印
     */
    private void printCharNumber(char[] number) {
        boolean isBeginning0 = true;
        for (int i = 0; i < number.length; i++) {
            if (isBeginning0 && (number[i] - '0') != 0) {
                isBeginning0 = false;
            }
            if (!isBeginning0) {
                // System.out.print(number[i] - '0');
                System.out.print(number[i]);
            }
        }
        System.out.println();
    }

以上是关于剑指Offer对答如流系列 - 打印1到最大的n位数的主要内容,如果未能解决你的问题,请参考以下文章

剑指Offer对答如流系列 - 剪绳子

剑指Offer对答如流系列 - 连续子数组的最大和

剑指Offer对答如流系列 - 最小的k个数

剑指Offer对答如流系列 - 礼物的最大价值

剑指Offer对答如流系列 - 从1到n整数中1出现的次数

剑指Offer对答如流系列 - 顺时针打印矩阵