题目:
输入数字n,按顺序打印出从1到最大的n位十进制数。比如输入3,则打印出1、2、3....999
这个题目貌似很简单,最直接的方法就是先求出最大的n位数,然后用一个循环从1开始逐个打印。但是要注意的是,当输入的n很大的时候,会产生溢出,需要考虑大数问题。
怎么表示大数?字符串或者数组。
1、字符串模仿数字加法
因为数字最大是n位,因此字符串长度应为n+1位(结束符号'\0'),当实际数字不够n位时,在字符串前半部分补0。
要做两件事儿:在字符串表达的数字上模拟加法,打印数字。
如何明确到了最大的n位数呢?虽然调用strcmp很简单,但是事件复杂度为O(n)。
注意到只有对“9999....9”加1的时候,才会在第一个字符(下标为0)产生进位,而其他情况都不会在第一个字符产生进位。因此当我们发现在加1的时候第一个字符产生了进位,则已经是最大的n位数,时间复杂度为O(1)。
bool Increment(char* number)
{
bool isOverflow=false;
int nTakeOver=0;
int nLength=strlen(number);
for(int i=nLength-1;i>=0;i--)
{
//nSum为低位需要加上的数值,nTakeOver为进位标志
int nSum=number[i]-'0'+nTakeOver;
//一进循环第一件事儿,给nSum++(累加)
if(i==nLength-1)
nSum++;
//如果nSum>=10,也就是要进位了,进循环
if(nSum>=10)
{
//如果是最高位进位,说明已经到了最大的n位数
if(i==0)
isOverflow=true;
//否则进行一般进位操作
else
{
nSum-=10;
nTakeOver=1;
number[i]='0'+nSum;
}
}
//如果没有进位,则进行一般低位+1操作,跳出循环,输出
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++)
{
//只有在碰到第一个非0的字符之后才开始打印,补位0不打印
if(isBeginning0 && number[i]!='\0')
isBeginning0=false;
if(!isBeginning0)
{
cout<<number[i];
}
}
cout<<" ";
}
void Print1ToMaxofNDigits(int n)
{
if(n<=0)
return;
char* number=new char[n+1];
//将number的前n个字节赋为‘0’
memset(number,'0',n);
number[n]='\0';
while(!Increment(number))
{
PrintNumber(number);
}
delete []number;
}
2、数字排列解法
换一种思路考虑这个问题,如果我们在数字前面补0,那么就会发现n位所有十进制数其实就是n个从0到9的全排列!也就是说,把数字的每一位都从0到9排列一遍,就得到了所有的二进制数。
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<<“ ”;
}
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';
Print1ToMaxOfDigitsRecursively(number,length,index+1);
}
}
void Print1ToMaxofNDigits(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';
Print1ToMaxOfNDgitsRecursively(number,n,0);
}
delete[] number;
}