面試題17:列印從1到最大的n位數
阿新 • • 發佈:2018-12-09
一、題目:
輸入數字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 測試結果