本文參考自《劍指offer》一書,代碼采用Java語言。
題目
輸入數字n,按順序打印出從1最大的n位十進制數。比如輸入3,則打印出1、2、3一直到最大的3位數即999。
思路
陷阱:n過大時是大數問題,不能簡單用int或者long數據輸出,需要采用字符串或者數組表達大數。
解決方法:通過字符數組char[]來進行輸出數字。
方法一:
1)在字符串表達的數字上模擬加法;
2)把字符串表達的數字打印出來。
方法二:
1)采用遞歸將每一位都從0到9排列出來;
2)把字符串表達的數字打印出來。
·測試算例
功能測試(輸入1,2,3……)
特殊輸入測試(輸入0,-1)
完整Java代碼
自己復習時寫的方法(比第一次寫的方法更清晰、簡潔點):
public void print1ToMaxOfNDights1s(int n) {
if(n<=0)
return;
char[] digit = new char[n];
for(int i=0;i<n;i++)
digit[i]='0';
for(int i=n-1;i>=0;i--) {
while(digit[i]!='9') {
int m=0;
digit[m]++;
while(m<n-1 && digit[m]>'9') {
digit[m]='0';
digit[m+1]++;
m++;
}
printdigits(digit);
}
}
}
private void printdigits(char[] digit) {
int m = digit.length-1;
while(digit[m]=='0')
m--;
for(int i=m;i>=0;i--)
System.out.print(digit[i]);
System.out.println();
}
(第一次寫的代碼,含測試)
/**
*
* @Description 面試題17:打印1到最大的n位數
*
* @author yongh
* @date 2018年9月17日 下午9:07:53
*/
// 題目:輸入數字n,按順序打印出從1最大的n位十進制數。比如輸入3,則
// 打印出1、2、3一直到最大的3位數即999。
public class Print1ToMaxOfNDigits {
//=========方法一============
/**
* 采用模擬加一的方法
*/
public void print1ToMaxOfNDigits(int n) {
if (n <= 0)
return;
char[] number = new char[n];
// 不能用foreach方法對nuber[]賦值
// for (char c : number) {
// c = '0';
// }
for (int k = 0; k < number.length; k++)
number[k] = '0';
while (!increment(number)) {
printCharNumber(number);
}
}
/**
* 對字符串進行加一操作,number達到最大值后返回true
* 最低位加一;所有位如果超過10,則進位
*/
private boolean increment(char[] number) {
int nTakeOver = 0; // 代表進位
for (int i = number.length - 1; i >= 0; i--) {
int nSum = (number[i] - '0') + nTakeOver; // 當前位置數字
// number[i]-'0'是把char轉化為int,nTakeOver代表進位
if (i == number.length - 1)
nSum++;
if (nSum >= 10) {
if (i == 0)
return true; // 超出范圍了
nTakeOver = 1;
nSum -= 10;
number[i] = (char) (nSum + '0');
} else {
number[i] = (char) (nSum + '0');
break; // 高位不變,可以直接跳出循環了
}
}
return false;
}
/**
* 打印字符數組形成的數字
* 書中方法:利用布爾變量isBeginning0來從第一個非零字符打印
*/
private void printCharNumber(char[] number) {
boolean isBeginning0 = true;
for (int i = 0; i < number.length; i++) {
if (isBeginning0 && (number[i] - '0') != 0) {
isBeginning0 = false;
}
if (!isBeginning0) {
// System.out.print(number[i] - '0');
System.out.print(number[i]);
}
}
System.out.println();
}
/**
* 打印字符數組形成的數字
* 自己的方法:找出第一個非零字符位置,往后進行打印
*/
private void printCharNumber2(char[] number) {
int beginner = number.length; // 不寫成number.length-1,以防寫出0
for (int i = 0; i <= number.length - 1; i++) {
if ((number[i] - '0') != 0) {
beginner = i;
break;
}
}
for (int i = beginner; i <= number.length - 1; i++) {
System.out.print(number[i]);
}
if (beginner != number.length) // 數字為0時,換行符不輸出
System.out.println();
}
//=========方法二============
/**
* 采用遞歸的方法
*/
public void print1ToMaxOfNDigits2(int n) {
if (n <= 0)
return;
char[] number = new char[n];
for (int k = 0; k < number.length; k++)
number[k] = '0';
for (int i = 0; i <= 9; i++) {
makeNumber(n, number, i, 0);
}
}
/**
* 生成數字
*/
private void makeNumber(int n, char[] number, int nNumber, int index) {
if (index == number.length - 1) {
number[index] = (char) (nNumber + '0');
printCharNumber2(number); // 打印數字代碼與第一個方法一樣
return;
} else {
number[index] = (char) (nNumber + '0');
for (int i = 0; i <= 9; i++) {
makeNumber(n, number, i, index + 1);
}
}
}
// ========測試代碼=============
void test(int nDigits) {
System.out.println("===test begin===");
System.out.println("method1:");
print1ToMaxOfNDigits(nDigits);
System.out.println("method2:");
print1ToMaxOfNDigits2(nDigits);
System.out.println("===test over===");
}
public static void main(String[] args) {
Print1ToMaxOfNDigits demo = new Print1ToMaxOfNDigits();
demo.test(-1);
demo.test(0);
demo.test(1);
demo.test(2);
}
}
===test begin=== method1: method2: ===test over=== ===test begin=== method1: method2: ===test over=== ===test begin=== method1: 1 2 3 4 5 6 7 8 9 method2: 1 2 3 4 5 6 7 8 9 ===test over=== ===test begin=== method1: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 method2: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 ===test over===
收獲
1.任何時候都不能輕視題目,像這道題看起來簡單,但其實涉及到大數問題,以后遇到數字相關的題目時要注意大數問題;
2.int類型和char類型轉化,通過±‘0’來實現,見int與char類型間的相互轉換。
3.打印字符串表示的數組,從第一個非零數字打印。
