面试题17:打印从1到最大的n位数

一、题目:

输入数字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 测试结果
在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/qq_41431406/article/details/84722247