被力扣简化的原版:剑指offer面试题17:打印从1到最大的n位数
输入数字 n,按顺序打印出从 1 到最大的 n 位十进制数。比如输入 3,则打印出 1、2、3 一直到最大的 3 位数 999。
分析思路
需要解决的问题:
- 考虑大数问题:
题目没有要求n的取值范围,所以会有int或者long型都溢出的可能。要求我们要用字符串来表示数字。 - 打印问题:
需要考虑如何打印出字符串表示的数。由于类似"00123"前导0的存在,我们要打印出符合我们阅读习惯的数字123,而不是00123,需要额外定义一个打印方法,这个PrintNumber函数从首个非0字符才开始打印。 - 如何得到从1到最大n位数
如果在数字前补0,那么n位所有十进制的数字其实就是n个从0到9的全排列,利用递归我们可以轻松实现。
代码实现
首先是对全排列的实现:
void Print1ToMaxOfDigits(int n) {
//对n取值范围的维护
if (n <= 0) {
return;
}
char[] number = new char[n];
for (int i = 0; i < 10; i++) {
number[0] = (char) (i + '0');
Print1ToMaxOfDigitsOrderly(number, n, 0);
}
}
//@param
//length:共n位数;
//index:记录已经填充好的位数;
void Print1ToMaxOfDigitsOrderly(char[] number, int length, int index) {
//当前n位数是否排列好
if (length - 1 == index) {
PrintNumber(number);
return;
}
//因为index位已经排列好,所以当前次递归排列的是index+1位
for (int i = 0; i < 10; i++) {
number[index + 1] = (char) (i + '0');
Print1ToMaxOfDigitsOrderly(number, length, index + 1);
}
}
接下来实现PrintNumber函数:
void PrintNumber(char[] number) {
boolean isBegin0 = true;//判断当前0是否为前导0
int len = number.length;
for (int i = 0; i < len; i++) {
//首个非0字符,此后的0都是有效数位
if (number[i] != '0' && isBegin0) {
isBegin0 = false;
}
//只打印有效数位
if (!isBegin0) {
System.out.print(number[i]);
}
}
System.out.println();
}
反思
书中提出一个char字符表示0~9的一个数字,浪费了8bit的char型字符能表达的256个字符的内存,能否提出更高效的方法实现?
请等待后续更新。