打印 1 到最大的 n 位數:輸入數字 n 按順序打印出從 1 最大的 n 爲十進制數。例如,輸入 3 , 打印 1, 2, ... , 999.ios
分析:注意沒有規定 n 的範圍,當 n 很大時,求最大的 n 位整數使用 int 或 long 類型都有可能會溢出。所以,最經常使用的解決方法是使用字符串或者是數組表達大數。git
使用字符串表示的時候,最直觀的方法就是使用字符 '0' ~'9' 之間的某一個字符來表示數字中的一位。由於數字最大是 n 位的,因此,須要一個 n + 1 的字符串(最後一個的符號位 '\0')。當實際數字不夠 n 位時,在字符串的前半部分補零。數組
首先將字符串的每一位初始化爲 '0',而後,每一次爲字符串表示的數字加 1,在打印出來。所以,至於要作兩件事:(一) 在字符串表達的數字上模擬加法,(二)把字符串表達的數字打印出來。函數
//主例程
void Print1ToMaxOfNDigits(int n)
{
if(n <= 0)
return;
char *number = new char[n + 1];
memset(number, '0', n);
number[n] = '\0';
while(!Increment(number))
{
PrintNumber(number);
}
delete [] number;
}spa
上述代碼中,Increment()函數實如今表示數字的字符串 number 上增長 1 ;而函數 PrintNumber()打印出 number 。這兩個看似簡單的函數都暗藏着小小的玄機。code
1) 須要知道在何時中止在 number 上加 1,一個最簡單的辦法就是每次遞增以後,都調用庫函數 strcmp()比較表示數字的字符串 number 和最大位數 n 位數字 「99...9」,若是想等表示已經到了最大的 n 位數並終止遞增。雖然調用 strcmp 很簡單,但對於長度爲 n 的字符串,它的時間複雜度爲 O(n)。ci
咱們注意到只有在「99...9」加 1 的狀況下,纔會在第一個字符(下標爲 0)的基礎上產生進位,而其餘全部的狀況都不會在第一個字符上產生進位。所以,當咱們發現加 1 在第一個字符上產生進位時,則已是最大的 n 位數,此時,Increment 函數返回 true,函數 Print1ToMaxOfNDigits 中的while 循環終止。rem
如下代碼實現了用 O(1) 的時間判斷是否已經達到了最大的 n 位數:字符串
bool Increment(char *number)
{
bool IsOverflow = false; //判斷是否溢出(超出最大位數 n)
int nTakeOver = 0; //進位
int length = strlen(number);it
for(int i = length - 1; i >= 0; i--)
{
int nSum = number[i] - '0' + nTakeOver;
if(i == length - 1)
nSum++; //每次調用數值增1
if(nSum >= 10)
{
if(i == 0)
IsOverflow = true; //在第一位字符處產生進位時,返回 true
else
{
nSum = nSum - 10;
nTakeOver = 1;
number[i] = '0' + nSum;
}
}
else
{
number[i] = '0' + nSum;
break;
}
}
return IsOverflow;
}
2)如何打印用字符串表示的數字:因爲 當數字不夠 n 位時,咱們在數字的前面補零,打印時這些補位的 0 不該該打印出來,所以,不能簡單的使用 printf 進行打印。爲此,咱們定義了函數 PrintNumber(),在這個函數裏,只有在碰到第一個非零的字符時纔開始打印,直到字符串的結尾。
void PrintNumber(char *number)
{
bool isBeginning0 = true;
int length = strlen(number);
for(int i = 0; i < length; i++)
{
if(isBeginning0 && number[i] != '0')
isBeginning0 = false;
if(!isBeginning0)
{
cout << number[i];
}
}
printf("\t");
}
總代碼:
//打印 1 到最大的 n 位數 #include<iostream> using namespace std; bool Increment(char *number) { bool IsOverflow = false; //判斷是否溢出(超出最大位數 n) int nTakeOver = 0; //進位 int length = strlen(number); //cout << length << endl; for(int i = length - 1; i >= 0; i--) { int nSum = number[i] - '0' + nTakeOver; if(i == length - 1) nSum++; //每次調用數值增1 if(nSum >= 10) { if(i == 0) IsOverflow = true; else { nSum = nSum - 10; nTakeOver = 1; number[i] = '0' + nSum; } } else { number[i] = '0' + nSum; break; } } return IsOverflow; } void PrintNumber(char *number) { bool isBeginning0 = true; int length = strlen(number); for(int i = 0; i < length; i++) { if(isBeginning0 && number[i] != '0') isBeginning0 = false; if(!isBeginning0) { cout << number[i]; } } printf("\t"); } //主例程 void Print1ToMaxOfNDigits(int n) { if(n <= 0) return; char *number = new char[n + 1]; memset(number, '0', n); number[n] = '\0'; while(!Increment(number)) { PrintNumber(number); } delete [] number; } int main() { int n; cin >> n; Print1ToMaxOfNDigits(n); cout << endl; system("pause"); return 0; }