题目:输入数字
,按顺序打印出从
到最大的
位十进制数。比如输入
,则打印出
一直到最大的
位数
。
当你第一次看到这道题目的时候,你可能会觉得很简单,使用一个循环把数打印出来就可以了嘛,所以你可能会写出下面的程序
public static void print1ToMaxOfNDigits(int n) {int number = 10;for (int i = 1; i < n; i++) {number *= 10;}for(int i = 1; i < number; i++) {System.out.println(i);}}
如果你仔细测试的话,你会发现当 比较大时,使用
int 类型已经不能表示这么大的数了(即使使用 long 类型整数也无法表示),所以当输入的 n 比较大时,就会发生溢出,这正是这道题考察的关键所在。
那么解决办法是什么呢? 那就是使用字符串来表示数字,所以这里的关键是使用字符串来模拟加法,这里我们使用自定义的 increment() 方法来进行模拟,该方法的返回值是一个布尔值,来表示是否已经达到了最大值,当字符串数字是 999...999 的时候,如果在继续增加则达到了最大值,这时如果在递增,在最高位就会产生进位,我们根据首位是否有进位来决定返回值,有进位时表示数字达到最大,返回 true,否则返回 false,代码如下
public class Print1ToMaxOfNDigits {public static void print1ToMaxOfNDigits(int n) {if (n < 0) {return;}// 使用字符数组来模拟数字char[] number = new char[n];// 初始化字符数组for (int i = 0; i < number.length; i++) {number[i] = '0';}// 当没有进位时,打印数值while(!increment(number)) {printNumber(number);}}// 模拟字符串加法的函数private static boolean increment(char[] number) {// 首位进位标志boolean isOverflow = false;// 是否有进位int takeOver = 0;for(int i = number.length - 1; i >= 0; i--) {// 获得第 n 位的数字表示,takeOver表示前一位的进位int nNumber = number[i] - '0' + takeOver;// 如果是个位,则加1if (i == number.length - 1) {nNumber++;}// 大于等于 10 表示有进位if (nNumber >= 10) {// 如果是最高位,则已经达到最大值了,设置首位进位标志为 trueif (i == 0) {isOverflow = true;} else {// 如果不是首位,那么设置有进位takeOver = 1;nNumber -= 10;// 将数字转为字符number[i] = (char)(nNumber + '0');}} else {// 如果没有进位,则转为字符number[i] = (char)(nNumber + '0');// 因为没有进位,所以后续也不会有进位,提前结束循环break;}}return isOverflow;}// 打印字符数组的方法,主要是控制前面的 0 不打印private static void printNumber(char[] number) {StringBuilder str = new StringBuilder();// 是否以 0 开始boolean beginZero= true;for(int i = 0; i < number.length; i++) {if (beginZero && number[i] != '0') {beginZero = false;}// 如果不以0开始了,才把字符添加进去if (!beginZero) {str.append(number[i]);}}System.out.println(str);}public static void main(String[] args) {print1ToMaxOfNDigits(2);}}
