剑指Offer面试题12(Java版):打印1到最大的n位数

题目:输入数字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

                 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 nlist = new ArrayList();
		for (int i = 0; i < n; i++) {
			nlist.add(0);
		}
		increment(nlist);
	}

	// 使数字每次+1然后输出
	public void increment(ArrayList 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 nlist) {
		Iterator 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);
	}
}


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