剑指offer面试12 打印1到最大的n位数

解题思路:

这题乍一看看上去还是比较容易,我们很自然的就想到先求出那个最大的n位数,然后在从1开始打印出来即可。这种解法存在一个致命的缺点,当n较大是,所需打印的数有很大部分超过了整形所能表示的范围。在java中,整形用4字节表示,所能表示的整数范围是-2147483648~2147483647。所能表示的数字也顶多是10位,因此当n较大时,我们需要转换思路。既然不能用整形来表示数字,那么可以想到用字符数组来存储数字的每一位。

从整体上来看,需要做两件事:(1)对字符数组代表的数字进行加1操作;(2)对加1后的字符数组进行打印,按照常规方式,需去除前面多余的'0'。具体步骤详见代码注释


/**打印1到最大的n位数
 *
 */
public class Solution {
	
	
	public static void print1ToMaxOfDigits(int n) {
		
		if (n <= 0) {
			System.out.println("Invalid Input");
		}
		
		//创建一个具有n个元素的字符数组,并设置初始值都为字符'0'
		char[] number = new char[n];
		for (int i = 0; i < number.length ; i++) {
			number[i] = '0';
		}
		
		while (!incrementIsOverflow(number)) {
			//如果+1后为越界,则将其打印出来
			printNumber(number);
		}
		
	}
	
	public static boolean incrementIsOverflow(char[] number) {
		//该标志位用于判断当前字符数组是否达到最大值,如果达到最大值,则停止继续+1的操作
		boolean isOverFlow = false;
		//进位符,表示在+1的过程中所产生的进位,开始为0;
		int nTakeOver = 0;
		//从字符数组的最后一位开始,进行+1操作,因为+1是在个位发生
		for (int i = number.length - 1; i >= 0; i--) {
			//取到当前数组的第i位上的数字字符
			char digit = number[i];
			//计算出当前字符所对应的数字加上进位后的结果
			//当前字符对应的数字用字符-'0'来表示
			int nSum = digit - '0' + nTakeOver;
			if (i == number.length - 1) {
				//如果当前位是数组的末尾,即数字的个位,则数值需要加1
				nSum++;
			}
			//判断当前字符对应的数字是否大于等于10
			if (nSum >= 10) {
				//如果当前字符对应的数字大于等于10
				if (i == 0) {
					//如果是最高位的数字大于等于10,则超过n位的最大整数
					isOverFlow = true;
				} else {
					//除最高位以外的其他位字符对应的数字大于等于10
					//产生进位
					nTakeOver = 1;
					nSum = nSum - 10;
					//更新number[i]的数字字符
					number[i] = (char) (nSum + '0');
				}
			} else {
				//如果当前字符对应的数字小于10,即不会产生进位
				//只需更新number[i]对应的数字字符
				number[i] = (char) (nSum + '0');
				//跳出循环,因为i之前的数字也不可能变,无需循环
				break;
			}
		}
		
		return isOverFlow;
	}
	
	/**
	 * 对每次进行+1操作后的数字进行打印,按照常规来打印
	 * @param number
	 */
	public static void printNumber(char[] number) {
		int i;
		//需要定位到数组中第一个非0的数字
		for (i = 0; i < number.length ; i++) {
			if (number[i] != '0') {
				//如果找到第一个不为0的字符,跳出循环
				break;
			}
		}
		//从i处开始打印字符数组中的数字
		while (i < number.length) {
			System.out.print(number[i]);
			i++;
		}
		//没打印完一个数字,下次从新行开始打印
		System.out.println();
		
	}


}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值