剑指offer-12.打印从 1 到最大的 n 位数

题目描述

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

题解:

如果题目中关于 n 位的整数没有限定 n 的取值范围,那么这个题目很可能就需要考虑大数问题,字符数组是一个简单、有效的表示大数的方法。

解法一:全排列问题用递归
数字的每一位都可能是 0-9 中的一个数,用递归;递归退出的条件是,已经设置了数字的最后一位。

class Solution {
    public void print1ToMaxOfNDigits(int n) {
        if (n <= 0)
            return;
        char[] number = new char[n];// 注意number[] 是从最高位往最低位开始存的
        print1ToMaxOfNDigits(number, 0);
    }

    private void print1ToMaxOfNDigits(char[] number, int index) {
        if (index == number.length) {
            printNumber(number);
            return;
        }
        for (int i = 0; i < 10; i++) {
            number[index] = (char) (i + '0');
            print1ToMaxOfNDigits(number, index + 1);
        }
    }

    private void printNumber(char[] number) {
        int index = 0;// 找到左边起,第一个非0的位置
        while (index < number.length && number[index] == '0') {
            index++;
        }
        int flag = 0;//标记是否全是0,全是0的话,最后就不用输出换行了
        if (index == number.length) {
            flag = 1;
        }
        while (index < number.length) {
            System.out.print(number[index++]);
        }
        if (flag != 1) {
            System.out.println();
        }
    }
}

解法二:在字符串上模拟数字加法(代码较长,不适合面试时手写)
从个位(即number[]的最高位)开始加,如果有进位,就继续往左加,否则跳出,如果最高位(number[0])有进位 ,则表示已经到最大值,退出打印。

class Solution {
    public void print1ToMaxOfNDigits(int n) {
        if (n <= 0)
            return;
        char[] number = new char[n];// 注意number[] 是从最高位往最低位开始存的
        for(int i=0;i<number.length;i++){
            number[i]='0';
        }
        while(!Increment(number)){
            printNumber(number);
        }
    }

    private boolean Increment(char[] number) {//返回是否成功加1
        boolean isOverflow=false;
        int nTakeOver=0;//表示上一位来的进位
        for(int i=number.length-1;i>=0;i--){//从最右边位,即个位加
            int nSum=number[i]-'0'+nTakeOver;
            if(i==number.length-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 void printNumber(char[] number) {
        int index = 0;// 找到左边起,第一个非0的位置
        while (index < number.length && number[index] == '0') {
            index++;
        }
        int flag = 0;//标记是否全是0,全是0的话,最后就不用输出换行了
        if (index == number.length) {
            flag = 1;
        }
        while (index < number.length) {
            System.out.print(number[index++]);
        }
        if (flag != 1) {
            System.out.println();
        }
    }
}

解法三:使用 BigInteger类,在线编程可用

compareTo方法来比较,小于则返回-1,等于则返回0,大于则返回1

构造器:
BigInteger(String val)
常用方法:
public BigInteger abs()
public BigInteger add(BigInteger val)
public BigInteger subtract(BigInteger val)
public BigInteger multiply(BigInteger val)
public BigInteger divide(BigInteger val)
public BigInteger remainder(BigInteger val)
public BigInteger pow(int exponent)
public BigInteger[] divideAndRemainder(BigInteger val)

class Solution {
    public void print1ToMaxOfNDigits(int n) {
        if (n <= 0)
            return;
        BigInteger start=new BigInteger("1");
        BigInteger increament=new BigInteger("1");
        StringBuffer sb=new StringBuffer();
        for(int i=1;i<=n;i++){
            sb.append('9');
        }
        BigInteger end=new BigInteger(sb.toString());
        while(start.compareTo(end)==-1||start.compareTo(end)==0){ // start <= end
            System.out.println(start);
            start=start.add(increament);
        }
    }

}

猜你喜欢

转载自blog.csdn.net/zxm1306192988/article/details/80865068