17、打印从1到最大的n位数

题目描述

      输入数字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();
    }
	
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值