参考:《剑指Offer第二版》
输入数字 n,按顺序打印出从 1 到最大的 n 位十进制数。比如输入 3,则打印出 1、2、3 一直到最大的 3 位数 999。
因为这里没有说明n的范围, 当n过大时,int和long 明显存不了那么大的数,因此这个题主要考查大数问题。
代码和解释:
① 非递归
/**
* 剑指 Offer 17. 打印从1到最大的n位数
* 非递归
*/
public static void printNumbers(int n) {
if( n<=0 ) return;
int[] res = new int[n];
//判断是否为最后一个数: 比如 n 为 2 时 ,打印到 99 就结束 , 99就为最后一个数
boolean isTakeOver = false;
while(true) {
int takeOver = 0; // 低位为10时 ,高位进1
//每次都从最低位开始进一, n - 1 为最低位 ,即个位
for(int i = n - 1 ; i >= 0 ; i--) {
int num = res[i] + takeOver;
//最低位进一
if(i == n - 1)
num++;
//最后一个数退出
if(i == 0 && num > 9) {
isTakeOver = true;
break;
}
//如果低位小于等于9 ,正常赋值,break出循环,输出
//如果低位大于9 ,比如为10 , 低位变为0 ,高位加1。(在纸上模拟一遍加法就明白了)
if(num<10) {
res[i] = num;
break;
}else {
num = 0;
res[i] = num;
takeOver = 1;
}
}
if(isTakeOver)
return;
print(res);
}
}
//碰到第一个不为 0 的数才开始打印
public static void print(int[] res) {
boolean isBegining0 = true;
for(int i = 0 ; i < res.length ; i++) {
if(isBegining0 && res[i] != 0 ) {
isBegining0 = false;
}
if(!isBegining0) {
System.out.print(res[i]);
}
}
System.out.print("\t");
}
② 递归
/**
* 剑指 Offer 17. 打印从1到最大的n位数
* 将问题转化为数字的全排列问题(n个从 0 到 9 的全排列)
* 递归全排列(递归代码更加简洁)
* 输出函数不变
*/
public static void printNumbers(int n) {
if( n<=0 ) return;
int[] res = new int[n];
for(int i = 0 ; i <= 9 ; i++) {
res[0] = i; //从第一个位置开始
printNumbersRecursively(res , n , 0); // n 个 0 到 9 的全排列
}
}
public static void printNumbersRecursively(int[] res, int n, int index) {
//结束条件
if(index >= (n - 1)) {
print(res);
return;
}
for(int i = 0 ; i <= 9 ; i++) {
res[index+1] = i;
printNumbersRecursively(res , n , index + 1 );
}
}
看看测试啪,噢值太大了,电脑卡住了/(ㄒoㄒ)/~~
因为电脑限制,换个小点的测试数据啪(谁懂其中的痛……)
测试结果:n为5时,没有问题。