1. 程式人生 > >面試題17:列印從1到最大的n位數

面試題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 測試結果
在這裡插入圖片描述