此题是一个大数问题,本质上可以归结为一个字符串的加1操作。需要注意溢出条件,动态分配内存的初始化不能忘记‘\0’ 勿忘释放内存。 打印大数时不能忘记前面的去零操作 字符串的加法是从低位开始的number[n-1];
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cmath>
using namespace std;
void Print1ToMaxNDigitsRecursively(char *numbers,int length,int index);
void Print(char *str);//打印用字符串表示一个n位的大数前面要去0
bool IncrementOne(char *numbers);//n位的字符串加1操作,当n位溢出时返回false 否则返回true;
void Print1ToMaxNDigits(int n)
{
if(n<1)
{
return;
}
char *numbers=new char[n+1];//用字符串表示一个n位的大数
memset(numbers,'0',n);
numbers[n]='\0';
int index=0;
for(int i=0;i<10;i++)//第0位的取值范围0到9
{
numbers[index]=i+'0';
Print1ToMaxNDigitsRecursively(numbers,n,index+1);//排列下一位。递归的思想和剑指offer的43题骰子的点数很像
}
delete [] numbers;//用完后记得释放内存。
}
void Print1ToMaxNDigitsRecursively(char *numbers,int length,int index)
{
if(index==length)//递归的终止条件为已经排列好n位数组的最后一位n-1位 对于n位的整数打印的位数从第0位到第n-1位
{
Print(numbers);
}
else
{
for(int i=0;i<10;i++)//n位数组的每一位都有可能是0~9中的一个数
{
numbers[index]='0'+i;
Print1ToMaxNDigitsRecursively(numbers,length,index+1);
}
}
}
void Print1ToMaxNDigits2(int n)
{
if(n<1)
{
return;
}
char *numbers=new char[n+1];//用字符串表示一个n位的大数
memset(numbers,'0',n);//初始化n位的大数为000000...0000
numbers[n]='\0';
while(!IncrementOne(numbers))//n位的字符串加1操作,当n位溢出时返回false 否则返回true;
{
Print(numbers);
}
delete [] numbers;// 用完后一定要记得释放内存。
}
bool IncrementOne(char *numbers)//n位的字符串加1操作,当n位溢出时返回false 否则返回true;
{
bool overFlow=false;
int countFlag=0;//进位符
int length=strlen(numbers);
for(int i=length-1;i>=0;i--)//最低位为numbers[length-1] n位字符串的加1操作。要对每一位进行判断是否有溢出
{
int sum=numbers[i]-'0'+countFlag;
if(i==length-1)//每次只对最低位加一个1 然后判断剩余的高位有没有溢出
{
sum++;
}
if(sum>=10)
{
if(i==0)//如果进位出现在最高位则表示溢出了。
{
overFlow=true;
}
countFlag=1;
sum=sum-10;
numbers[i]=sum+'0';
}
else
{
numbers[i]=sum+'0';
countFlag=0;//进位标志置为0;
}
}
return overFlow;
}
void Print(char *str)
{
if(str==NULL)
{
return;
}
while((*str)!='\0'&&(*str)=='0')//找到第一个非零数,跳出循环时的*str为第一个非零数
{
str++;
}
if(*str!='\0')//不打印全是00000 的情况
{
printf("%s\t",str);
}
}
int main()
{
Print1ToMaxNDigits(4);
//Print1ToMaxNDigits2(4);
return 0;
}