1.题目描述
输入数字n,按顺序打印出从1最大的n位十进制数。比如输入3,则打印出1、2、3一直到最大的3位数即999。
2.分析
- 如果简单的使用int或者long long类型来打印出结果,那么当n很大,比64还大的时候,就会出现溢出,无法打印出来
- 应该使用字符串来模拟数字加分,才可能没有数字长度限制
3.模拟加减法解法
A.源码–使用vector<char>
来保存数据
#include <memory>
#include <cstring>
#include <vector>
#include <iostream>
using namespace std;
class Digit
{
friend ostream& operator<<(ostream& os,const Digit& digit);
public:
//是否溢出判断
bool isOverflow;
Digit(){}
Digit(const int n):isOverflow(false){_digit = std::move(vector<char>(n,'0'));}
Digit& operator ++()
{
isOverflow = false;
//使用反向迭代器进行模拟计算
auto rbegin_iter = _digit.rbegin(),rend_iter = _digit.rend();
for(auto reiter = rbegin_iter;reiter!=rend_iter;++reiter)
{
int number = *reiter - '0' ;
if(reiter == rbegin_iter)
++number;
if(number >=10)
{
number -=10;
if( reiter+1 != rend_iter)
*(reiter+1) +=1;
else
isOverflow = true;
}
*reiter = number + '0';
}
return *this;
}
Digit& operator =(const Digit& rhs)
{
this->_digit = rhs._digit;
this->isOverflow = rhs.isOverflow;
return *this;
}
Digit operator ++(int)
{
Digit preDigit;
preDigit = *this;
++(*this);
return preDigit;
}
private:
vector<char> _digit;
};
//输出字符串vector<char> _digit
ostream& operator<<(ostream& os,const Digit& digit)
{
int length = digit._digit.size();
int index = 0;
while(digit._digit[index]=='0') ++index;
for(;index<length;++index)
os<<digit._digit[index];
return os;
}
void PrintOneToMaxOfNDigits_1(int n)
{
if (n <= 0)
return;
Digit digit(n);
while(!(++digit).isOverflow)
{
cout << digit<<" ";
}
cout <<endl;
}
int main()
{
PrintOneToMaxOfNDigits_1(3);
return 0;
}
运行结果图:
B.源码–使用char* _digit
来保存数据
#include <memory>
#include <cstring>
#include <vector>
#include <iostream>
using namespace std;
class Digit2
{
friend ostream& operator<<(ostream& os,const Digit2& digit);
public:
bool isOverflow;
Digit2(){//初始化_digit
_digit = new char[1];
_digit[1] = '\0';
}
Digit2(const int n):isOverflow(false)
{
//初始化_digit
_digit = new char[n+1];
memset(_digit,'0',n);
_digit[n] = '\0';
}
~Digit2(){delete []_digit;}
Digit2& operator ++()
{
isOverflow = false;
int length = strlen(_digit);
for(int index=length-1;index >=0;--index)
{
int number = _digit[index] - '0';
if(index ==length-1)
++number;
if(number>=10)
{
number -=10;
if(index == 0)
isOverflow = true;
else
++_digit[index-1];
}
_digit[index] = number + '0';
}
return *this;
}
Digit2& operator =(const Digit2& rhs)
{
if(&rhs !=this)
{
delete []this->_digit;
int length = strlen(rhs._digit);
this->_digit = new char[length + 1];
for(int i=0;i<=length;++i)
{
this->_digit[i] = rhs._digit[i];
}
this->isOverflow = rhs.isOverflow;
}
return *this;
}
Digit2 operator ++(int)
{
Digit2 preDigit;
preDigit = *this;
++(*this);
return preDigit;
}
private:
char* _digit;
};
ostream& operator<<(ostream& os,const Digit2& digit)
{
int length = strlen(digit._digit);
int index = 0;
while(digit._digit[index] == '0') ++index;
for(;index<length;++index)
os<<digit._digit[index];
return os;
}
void PrintOneToMaxOfNDigits_1(int n)
{
if (n <= 0)
return;
Digit2 digit(n);
while(!(++digit).isOverflow)
{
cout << digit<<" ";
}
cout <<endl;
}
int main()
{
PrintOneToMaxOfNDigits_1(3);
return 0;
}
运行结果:
C.全排列递归–源码
#include <memory>
#include <cstring>
#include <vector>
#include <iostream>
using namespace std;
class Digit
{
friend ostream& operator<<(ostream& os,const Digit& digit);
public:
Digit():length(0){_digit=std::move(vector<char>(0));}
Digit(const int n):length(n){_digit=std::move(vector<char>(n,'0'));}
vector<char> _digit;
int length;
};
ostream& operator<<(ostream& os,const Digit& digit)
{
int index = 0;
while(digit._digit[index]=='0')++index;
if(index == digit.length)
{
os<<'0';
return os;
}
for(;index!=digit.length;++index)
os<<digit._digit[index];
return os;
}
void RecursionPrint1ToN(Digit& digit,int index,bool& isBeginning0)
{
if(index == digit.length)
{
//第一次不打印,第一次是0
if(isBeginning0)
{
isBeginning0 = false;
return;
}
cout << digit<<" ";
return;
}
for(int i=0;i<10;++i)
{
digit._digit[index] = '0'+i;
RecursionPrint1ToN(digit,index+1,isBeginning0);
}
}
void Print1ToMaxN(int n)
{
if(n<=0)
return;
Digit digit(n);
//第一次不打印出来,第一个数是0
bool isBeginning0 = true;
RecursionPrint1ToN(digit,0,isBeginning0);
}
int main()
{
//PrintOneToMaxOfNDigits_1(4);
Print1ToMaxN(8);
}
4.结论
这道题使用了字符串模拟了加法如何加减,使用vector<char>
的效率比char *
低。当n的大小是9,也就是要进行上亿次加法。