剑指offer 面试题17:打印从1到最大的n位数(java)

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

分析:
  由于没有给n的范围,所以要考虑到大数问题。

第一种方法(模拟加法):
  在字符串的数字上模拟加法,定义一个长度为n的字符数组,初始化为’0’, 把字符串表达的数字打印出来
  定义一个长度为n的数组,每一位表示数字的一位
  在数字的最后一位每次加一,加到10就归零,定义一个变量来表示进位,加到10的时候进位的变量为1
定义一个判断是否最大的n位数,如果第n位上的数加到10,表明已经到了最大的n位数。就停止加一。
  打印时,考虑到可能089这种结果要打印成89,所以从第一个不为0的位置开始打印

public static void main(String[] args) {
        printToMaxOfDigits(3);
    }
    public static void printToMaxOfDigits(int n){
        if(n<=0){
            return;
        }
        char[] number=new char[n];
        //给数组初始化为'0'
        for(int i=0;i<number.length;i++){
            number[i]='0';
        }
        while(!Increment(number)){
            PrintNumber(number);
        }
    }
    //此方法为在数字的字符串number上加1
    public static boolean Increment(char[] number){
        boolean isOverflow=false;//判断是否溢出
        int nTakeOver=0;
        int nLength=number.length;
        for(int i=nLength-1;i>=0;i--){
            int nSum=number[i]-'0'+nTakeOver;//将第i位的字符转换成数字+进位
            if(i==nLength-1){
                nSum++;
            }
            if(nSum>=10){
                if(i==0)
                    isOverflow=true;
                else{
                    nSum-=10;
                    nTakeOver=1;
                    number[i]= (char) ('0'+nSum);
                }
            }else{
                number[i]= (char) ('0'+nSum);
                break;
            }
        }
        return isOverflow;
    }
    //打印数字
    private static void PrintNumber(char[] number) {
        boolean isBeginning0 = true;//判断当前数字的前面是否是0  如果是零 就从下一位开始输出
        int nLength = number.length;
        for (int i = 0; i < nLength; ++i) {
            if (isBeginning0 && number[i] != '0') {//碰到第一个非0字符之后才开始打印。
                isBeginning0 = false;
            }
            if (!isBeginning0) {
                System.out.print(number[i]);
            }
        }
        System.out.println();
    }

第二种方法(全排列):
  由于模拟了整数的加法,代码有点长。

  n位所有十进制数其实就是n个从0到9的全排列。

  数字的每一位都可能是0-9中的一个数,然后设置下一位。注意这里设置是从下标为0开始设置的,逐步进行递归,递归结束条件就是已经设置了数字的最后一位。

public static void main(String[] args) {
        printToMaxOfDigits(2);

    }
    //打印1到最大的n位数的主方法
    public static void printToMaxOfDigits(int n){
        if(n <= 0){
            return;
        }
        char number[] = new char[n];
        for (int i = 0; i < number.length; i++) {
            number[i] = '0';
        }
        for (int i = 0; i < 10; ++i) {
            number[0] = (char) (i + '0');//记录的是最高位的值
            printToMaxOfNDigitsRecursively(number, n, 0);
        }
    }
    //利用递归实现1到最大的n位数的全排列
    public static void printToMaxOfNDigitsRecursively(char[] number, int n, int index) {
        if(index == n - 1){
            PrintNumber(number);
            return;
        }
        for (int i = 0; i < 10; ++i) {
            number[index + 1] = (char) (i + '0');
            printToMaxOfNDigitsRecursively(number, n, index + 1);
        }
    }
    //打印数字
    private static void PrintNumber(char[] number) {
        boolean isBeginning0 = true;//判断当前数字的前面是否是0  如果是零 就从下一位开始输出
        int nLength = number.length;
        for (int i = 0; i < nLength; ++i) {
            if (isBeginning0 && number[i] != '0') {//碰到第一个非0字符之后才开始打印。
                isBeginning0 = false;
            }
            if (!isBeginning0) {
                System.out.print(number[i]);
            }
        }
        System.out.println();
    }

你可能感兴趣的:(剑指offer)