一、题目:
输入数字n,按顺序打印从1到最大的n位的十进制数。比如输入3,则打印出1、2、3一直到最大的3位数999
1.1 解法
两种不同的方法解决这个问题:
1、是字符串上模拟数字加法,用字符串表达大数
2、使用全排列递归调用
二、字符串上模拟加法
2.1 思想:
用字符串表示数字时,字符串里的每一个字符都是0-9之间的某一个字符,用来表示数字的其中一位,数字最大是n位,我们用一个长度为n+1的字符串,字符串的最后一位是\0,当实际数字不够n位时,在字符串的前半部分补0
2.2模拟加法及代码实现
模拟加法 实现在表示字符串number上加1 用number代替大数
字符串的每一个数字都初始化为0,每一次加一后打印
void PrintToMaxOfDigits(int n)
{
if(n<=0)
return;
char *number=new char[n+1]; //长度为n+1的字符串
memset(number,'0',n); //每一个数字都初始化为0
number[n]='\0'; //字符串最后一个为 \0
//如果字符串代表的数字每加一,打印字符串
while(!Increment(number))
{
PrintNumber(number);
}
delete []number;
}
2.3判断函数什么时候终止及代码实现
实现在表示数子的字符串number上加1,若要判断什么时候停止加一,即每次加一后都要判断是否已达到最大的n位数
1、调用库函数strcmp比较字符串number和最大的n位数,如果相等则表示已经到达最大的n位数并终止递增,但由于长度为n,时间复杂度为o(n),
2、在数字分析中,我们发现只有数字位9,99,999等时,才会在第一个字符(下标为0)的基础上产生进位,则此时数字已经是最大的n位数,此时Increment返回true,函数中的while循环终止,时间复杂度仅为O(1)
bool Increment(char* number)
{
bool isOverflow=false;//溢出 代表整个n位数未达最大数
int nTakeOver=0;//进位
int nLength=strlen(number);
for(int i=nLength-1;i>=0;i--)
{
int nSum=number[i]-'0'+nTakeOver;//求出带进位的i的值 每次调用bumber[i]的值已经发生变化,依次是0-9
//如果是最个位,加一
if(i==nLength-1)
nSum++;
//需要进位
if(nSum>=10)
{
//最高位number[0]为0,要进位,代表已经是最大数
if(i==0)
isOverflow=true;
else
{
nSum-=10;
//使下一位的开始值从0变为1
nTakeOver=1;
number[i]='0'+nSum;//该句之后,for 循环跳到字符串的下一位,本位上依旧从0开始,相当于各位恢复到0,下次for循环从十位开始
}
}
else //该位数字在0以内,不需要进位
{
number[i]='0'+nSum;
break;
}
}
return isOverflow;
}
2.4把字符串实现的数字打印出来
实现打印number 数字位不够时,前面补0,但补位的0不打印
,将011打印为11 ,即只有碰到第一个非0的字符之后才开始打印,直至字符串的结尾
void PrintNumber(char* number)
{
//字符逐个输出
bool isBegining0=true;//是否以0开头,默认为true
int nLength=strlen(number);
for(int i=0;i<nLength;++i)
{
//如果开头不是0,且isBegining当前值为true,则将isBegining改为false
if(isBegining0 && number[i]!='0')
isBegining0=false;
//只有在isBegining0为false时,才打印输出
if(!isBegining0)
{
printf("%c",number[i]);
}
}
printf("\t");
}
三、使用全排列递归调用
3.1思想
n位所有十进制数字就是n个从0-9的全排列,将数字的每一位都从0到9排列一遍,就可得到所有的十进制数,只是在打印时,排在前面的0不打印出来
3.2递归调用函数,给各位加一
void Print1ToMaxOfDigitsRecuisively(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';
Print1ToMaxOfDigitsRecuisively(number,length,index+1);
}
}
3.3高位上的0-9的依次排列
void PrintToMaxOfNDigits(int n)
{
if(n<=0)
return;
char* number=new char[n+1];
number[n]='\0';
//从高位开始全排列,1-9
for(int i=0;i<10;i++)
{
number[0]=i+'0';
Print1ToMaxOfDigitsRecuisively(number,n,0);
}
delete[] number;//释放内存
}
四、测试以及结果
4、1 测试代码
int main()
{
//PrintToMaxOfDigits(2);
PrintToMaxOfNDigits(2);
return 0;
}
4、2 测试结果