今天看到《剑指offer》中一道和大数问题有关的题目,之前碰到过,但也是一扫而过,没有特别在意。特意在此记录一下相关思路和代码。
问题描述
输入数字n,按顺序打印从1到最大的n位数十进制数。比如输入3,则打印出1,2,3一直到最大的3位数999。
思路
- 字符串里的每一个字符都是‘0’—‘9’中的字符,对应了数字中某一位。字符串的长度应为n+1,最后一位是‘\0’
- 首先把字符串的每一个数字都初始化为‘0’,然后每一次为字符串表示的数字加1,再打印出来。
- 模拟加法需要注意停止的条件,即达到了最大n位数时就要停止加一
- 打印需要注意符合阅读习惯,前面的零不需要打印
个人在看完讲解后,理解了思路,但是用代码复现的能力还是不够。
#include <iostream>
using namespace std;
//模拟加法:+1操作
bool Increment(char* number) {
bool isOverflow = false;
int nTakeOver = 0;//记录进位用的
int nLength = strlen(number);//获取字符串的长度,不包括'\0'
//从字符串的后面往前,表示数字从个位开始处理
for (int i = nLength - 1; i >= 0; --i) {
int nSum = number[i] - '0' + nTakeOver;//字符转为int
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) {
cout << number[i];
}
}
cout << endl;
}
void Print1ToMaxOfNDigits(int n) {
if (n <= 0) {
return;
}
//初始化
char* number = new char[n + 1];
memset(number, '0', n);
number[n] = '\0';
while (!Increment(number)) {
PrintNumber(number);
}
}
int main() {
Print1ToMaxOfNDigits(9);
return 0;
}