题目:输入数字n,按顺序打印出从1最大的的n位数十进制数。比如输入3,则打印出1,2,3一直到最大的3位数即999.
1、跳进面试官的陷阱
这个题目看起来很简单。我们看到这个问题后,最容易想到的办法是求出最大的n位数,然后用一个循环从1开始逐个打印。于是我们很容易写出下面的代码。
void print1ToMaxOfNDigits(int n){
int number =1;
int i =0;
while(i++< n)
number*=10;
for(int i =1;i<number;++i)
System.out.println(i);
}
初看之下没有问题,但如果仔细分析这个问题,我们就能注意到面试官没有规定n的范围。当输入n很大的时候,我们求最大的n位数是不是用整型(int)或者长整型(long long)都会溢出?也就是说我们需要考虑大数问题。这是面试官在这道题里设置的一个大陷阱。
2、在字符串上模拟数字加法的解法:
经过前面的分析,我们很自然的想到解决这个问题需要一个大数。最常用的也是最容易的用字符串或者数组表达大数。接下来我们用数组来解决大数问题。
实现下面的代码:
/**
*
*/
package swordForOffer;
import java.util.ArrayList;
import java.util.Iterator;
/**
* @author JInShuangQi
*
* 2015年7月31日
*/
public class E12Print1ToMaxOfNDigits {
public void outPutOneToMaxNDigits(int n) {
// 用nlist表示数n,nlist[0]表示n的最低位
ArrayList<Integer> nlist = new ArrayList<Integer>();
for (int i = 0; i < n; i++) {
nlist.add(0);
}
increment(nlist);
}
// 使数字每次+1然后输出
public void increment(ArrayList<Integer> nlist) {
int carrybit = 0;
boolean end = false;
while (true) {
for (int i = nlist.size() - 1; i >= 0; i--) {
int digit = nlist.get(i);
int sum = digit + carrybit;
if (i == (nlist.size() - 1)) {
sum += 1;
}
if (sum >= 10) {
// 最高位产生进位,达到最大值,停止输出
if (i == 0) {
end = true;
}
sum = sum - 10;
carrybit = 1;
} else {
carrybit = 0;
}
nlist.set(i, sum);
}
output(nlist);
if (end) {
break;
}
}
}
// 输出数字,将高位的0舍掉
public void output(ArrayList<Integer> nlist) {
Iterator<Integer> ite = nlist.iterator();
int num;
// 找到第一个为0的位置
boolean first = false;
while (ite.hasNext()) {
if (first) {
System.out.print(ite.next());
continue;
}
if ((num = ite.next()) != 0) {
first = true;
System.out.print(num);
}
}
System.out.println();
}
public static void main(String[] args) {
E12Print1ToMaxOfNDigits test = new E12Print1ToMaxOfNDigits();
test.outPutOneToMaxNDigits(2);
}
}