题目:输入数字n,按顺序打印出从1最大的n位十进制数。比如输入3,则打印出1、2、3一直到最大的3位数即999。
陷阱:用int或long表示整数时的溢出
方法1:用字符串解决大数问题。
void PrintToMaxOfNDigits(int n){
if (n <= 0){
return;
}
char *number = new char[n + 1];
memset(number, '0', n);
number[n] = '\0';
while(!Increment(number)){
PrintNumber(number);
}
delete []number;
}
bool Increment(char* number){
bool isOverflow = false;
int nTakeOver = 0;
int nLength = strlen(number);
for (int i = nLength - 1; i >= 0; i --){
int nSum = number[i] - '0' + nTakeOver;
if (i == nLength - 1){
nSum ++;
}
if (nSum >= 10){
if (i == 0){
isOverflow = true;
}
else {
nSum -= 10;
nTakeOver = 1;
number[i] = '0' + nSum;
}
}
else {
number[i] = '0' + nSum;
break;
}
}
return isOverflow;
}
void PrintNumber(char* number){
bool isBeginning0 = true;
int nLength = strlen(number);
for (int i = 0; i < nLength; ++ i){
if (isBeginning0 && number[i] != '0'){
isBeginning0 = false;
}
if (!isBeginning0){
printf("%c", number[i]);
}
}
printf("\t");
}
方法2:把数字的每一位从0到9排列一遍,打印时数字排在前面的0不打印就可以。全排列的递归算法是,数字的每一位都可能是0~9中的一个数,然后设置下一位。递归结束的条件是我们已经设置了数字的最后一位。
void Print1ToMaxOfDigits (int n){
if (n <= 0){
return;
}
char* number = new char[n + 1];
number[n] = '\0';
for (int i = 0; i < 10; ++i){
number[0] = i + '0';
Print1ToMaxOfNDigitsRecursively(number, n, 0);
}
delete[] number;
}
void Print1ToMaxOfNDigitsRecursively(char* number, int length, int index){
if (index == length - 1){
PrintNumber(number);
return;
}
for (int i = 0; i < 10; ++i){
number[index + 1] = i + '0';
Print1ToMaxOfNDigitsRecursively(number, length, index + 1);
}
}
测试用例:
- 功能测试(输入1、 2、 3)
- 特殊输入测试(输入-1、0)
思考题:用一个char型字符表示十进制数字中的一位。8个bit的char型字符最多能表示256个字符,而十进制数字只有0~9的10个数字。因此用char型字符串来表示十进制的数字并没有充分利用内存,有一些浪费。考虑有没有更高效的方式来表示大数?
相关题目:实现任意两个整数的加法。