题目描述
输入数字n,按照顺序打印出从1到最大的n位十进制数字。比如输入3,则打印1、2、3……999
思考
首先想到:求出最大的n位数,然后循环打印:
// 基本思路:先求出最大的n位数,遍历打印
public static void Print1ToMaxOfNDigits_1(int n) {
for (int j = 1; j < Math.pow(10, n); j++) {
System.out.println(j);
}
}
问题:输入的n可能很大,数据溢出,造成大数问题
解决:使用字符串或者数组表示大数
1、选择字符串表示大数,在字符串表达的数字上模拟加法;
2、把字符串表达的数字打印出来(选择性打印)
代码:
package Sword;
import javax.swing.text.StyledEditorKit.BoldAction;
/**
* 打印从1到最大的n位数
* 陷阱:考虑大数问题,就是数据溢出问题
* @author tyler 2019-12-31
*
*/
public class BigData {
public static void main(String[] args) {
Print1ToMaxOfNDigits_1(2);
Print1ToMaxOfNDigits_2(1);
}
// 基本思路:先求出最大的n位数,遍历打印
public static void Print1ToMaxOfNDigits_1(int n) {
for (int j = 1; j < Math.pow(10, n); j++) {
System.out.println(j);
}
}
//--- 字符串表示大数字-----------------------------------
public static void Print1ToMaxOfNDigits_2(int n) {
// 异常处理
if (n <= 0 ) {
return ;
}
char[] number = new char[n];
initCharArray(number); // 初始化
while (!Increment(number)) { // 在表示数字的字符串number上加1
PrintNumber(number); // 打印number
}
}
// 功能:初始化字符串表示数字
public static void initCharArray(char[] chars) {
for (int i = 0; i < chars.length; i++) {
chars[i] = '0';
}
}
// 功能:在表示数字的字符串number上加1,返回判断标识:是否到了最大n位数
public static boolean Increment(char[] number) {
// 判断是否到了最大的n位数
boolean isOverflow = false;
// 进位数
int takeOver = 0;
for (int i = number.length-1; i >= 0; i--) {
int sum = number[i] - '0' + takeOver; // 每一位减去‘0’加进位
if (i == number.length -1) { // 末位加1
sum++;
}
if (sum >= 10) { // 加了之后有进位
if (i == 0) {
isOverflow =true; // 到了最大的n位数了,不用进位了
}else { // sum >= 10 ,i 不为0,不是最大n位数,进位
sum -= 10;
takeOver = 1;
number[i] = (char)('0' + sum);
}
}else { // 加了之后没有进位
number[i] = (char)('0' + sum);
break; // 跳出当前循环,不用再循环
}
}
return isOverflow; // 为真表示加1完成,并且到了最大n位数;为假表示加1完成,但是没到最大n位数
}
// 功能:打印字符串表示的数字
public static void PrintNumber(char[] number) {
// 字符串前面为0的部分不打印,找到开始打印的那个0,打印之后的内容
boolean isBeginning = false; // 标识
for (int i = 0; i < number.length; i++) {
if (!isBeginning && number[i] != '0') {
isBeginning = true;
}
if (isBeginning) {
System.out.println(number[i]);
}
}
}
// ---------------全排列表示数字并且打印----------------------------
/**
* 把问题转成数字排列的解法
* 相当于回溯法
* @param n
*/
public static void print1ToMaxOfNDigits(int n) {
if (n <= 0) {
return;
}
char[] number = new char[n];
print1ToMaxOfNDigitsRecursively(number, n, 0);
}
/**
* 递归核心
* @param number
* @param length
* @param index 字符串的第几位
*/
public static void print1ToMaxOfNDigitsRecursively(char[] number, int length, int index) {
if (index > length - 1) {
printNumber(number);
return;
}
for (int i = 0; i < 10; i++) {
number[index] = (char) (i +'0');
print1ToMaxOfNDigitsRecursively(number, length, index + 1);
}
}
/**
* 根据字符串打印出数字
* @param number
*/
private static void printNumber(char[] number) {
// 默认字符串不以0开始
boolean isBegining0 = true;
for (int i = 0; i < number.length; i++) {
if (isBegining0 && number[i] != '0') {
isBegining0 = false;
}
if (!isBegining0) {
System.out.print(number[i]);
}
}
System.out.println();
}
}