输入数字n,按顺序打印从1到最大的n位数。比如输入3,则依次打印1、2、3一直到最大的3位数999
知识点
char与int之间的加减法(比如 1 + ‘0’ 和 ‘1’ - ‘0’)
字符串解决大数问题
最常用也是最容易的方法便是使用字符串或者数组来表示大数。接下来我们用字符串来解决上述问题。
用字符串表示很大的整数时,一个很直观的方法便是字符串的每一位都用‘0’~‘9’的字符来填充,用以表示大数的某一位。由于题目要求有n位数,那么我们需要的字符串长度为n+1(字符串最后一位是结束符‘\0’)。当实际数字不够n位时,前面的部分用‘0’填充。
这样转化以后,还有两个关键的问题需要解决。一是如何用字符串模拟整数的自增1运算,二是如何打印出来以符合我们日常书写整数的习惯(即数字前面的0不打印)。
要提前说明的一点:在C++中,字符的‘+’‘-’等运算实质上是ASC码进行相应运算。
先说说如何用字符串模拟整数的自增1运算:其实很简单,我们只需要从字符串的最后一位开始自增1(利用上述说明的一点即可),同时需要利用一个变量记录进位。那么何时自增结束呢(即达到最大的999……999,n个9):显然,仅当999……999(n个9)在其基础上自增1的时候,才会在字符串第一位产生进位。我们可以利用这个条件来判断自增结束,这样可以在O(1)的时间内进行判断。
接下来便考虑如何打印:其实有了字符串每一位初始化为‘0’的前提之后,我们打印时只需要从遇到的第一个非‘0’符开始打印即可。
- 不考虑大数问题解法
#elif 0//不考虑大数解法
class Solution {
public:
vector<int> printNumbers(int n) {
vector<int> res;
if (n <= 0)
return res;
int num = pow(10,n);
for(int i = 1; i <num;++i)
res.push_back(i);
return res;
}
};
#endif
- 通过使用char数组进行求解大数问题
#if 1
class Solution {
public:
vector<int> res;
vector<int> printNumbers(int n) {
if (n <= 0) return res;
//创建一个能容纳最大值的字符数组,由于有一位要存储'\0',因此要开大一格
char* number = new char[n + 1];
memset(number, '0', n);//初始全部设置为0
number[n] = '\0';//第n位设为'\0'
while (!Increment(number)){
PrintNumber(number);
}
delete[]number;//注意要释放内存
return res;
}
bool Increment(char* number) {//形参传递char*指针
bool isOverflow = false;//检测是否越界
int nTakeOver = 0;//存储进位
int nLength = strlen(number);//长度为n,不是n+1
for (int i = nLength - 1; i >= 0; i--){
int nSum = number[i] - '0' + nTakeOver;//首先将字符转化为int型数字
if (i == nLength - 1)//如果是第一位,加1(循环变量)
nSum++;
if (nSum >= 10){ //有进位
if (i == 0)//如果是最高位有进位,说明超过了给定得到最大值,越界
isOverflow = true;
else{//非最高位有进位
nTakeOver = 1;
number[i] = nSum - 10 + '0';//对第i位进行设置
}
}
else{//没有进位;设置第i位数字;并直接跳出循环
number[i] = nSum + '0';
break;
}
}
return isOverflow;
}
void PrintNumber(char* number) {
//形参传递char*指针,此处改变形参number指向的位置,不会使原始的number指针所指位置改变
string s = "";
bool isBegin0 = true;
while (*number != '\0')
{
if (isBegin0 && *number != '0')
isBegin0 = false;
if (!isBegin0)//碰到'0',则不输出
{
s += *number;
}
number++;
}
int num = stoi(s);//转为整数
res.push_back(num);
}
};
- 通过使用string进行求解大数问题
class Solution {
public:
vector<int> res;
vector<int> printNumbers(int n) {
if (n <= 0) return res;
string number(n,'0');//创建一个能容纳最大值的字符数组
while (!Increment(number)) {//初始全部设置为0
saveNumber(number);
}
return res;
}
bool Increment(string& number) {//注意要使用引用传递,否则无法修改number
bool isOverFlow = false;//检测是否越界
int nTakeOver = 0;//存储进位
int nLength = number.size();
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{
nTakeOver = 1;
number[i] = nSum - 10 + '0';//int 转char
}
}
else{
number[i] = nSum + '0';//int 转char
break;//如果没有进位,不用继续循环计算高位数值,直接跳出循环
}
}
return isOverFlow;
}
void saveNumber(string number) {//由于此处输出,不需要修改number,因此不需要加引用
string s = "";
bool isBegin0 = true;
string::iterator it = number.begin();
while (it != number.end()){
if (isBegin0 && *it != '0') isBegin0 = false;
if (!isBegin0){
s += *it;
}
it++;
}
res.push_back(stoi(s));
}
};