【剑指 Offer】剑指 Offer 17. 打印从1到最大的n位数 【Java - 大数问题 - 递归 - 模拟】

参考:《剑指Offer第二版》

输入数字 n,按顺序打印出从 1 到最大的 n 位十进制数。比如输入 3,则打印出 1、2、3 一直到最大的 3 位数 999。

因为这里没有说明n的范围, 当n过大时,int和long 明显存不了那么大的数,因此这个题主要考查大数问题

代码和解释:

① 非递归

/**
 * 剑指 Offer 17. 打印从1到最大的n位数
 * 非递归
 */
   public static void printNumbers(int n) {

   	   if( n<=0 ) return;
   	
       int[] res = new int[n];
       
       //判断是否为最后一个数: 比如 n 为 2 时 ,打印到 99 就结束 , 99就为最后一个数
       boolean isTakeOver = false;
       
       while(true) {
       	
       	int takeOver = 0; // 低位为10时 ,高位进1
       	
       	//每次都从最低位开始进一, n - 1 为最低位 ,即个位 
       	for(int i = n - 1 ; i >= 0 ; i--) {
       		
       		int num = res[i] + takeOver; 
       		
       		//最低位进一
       		if(i == n - 1) 
       			num++; 
       		
       		//最后一个数退出
       		if(i == 0 && num > 9) {
       			isTakeOver = true;
       			break;
       		}
       		
       		//如果低位小于等于9 ,正常赋值,break出循环,输出
       		//如果低位大于9 ,比如为10 , 低位变为0 ,高位加1。(在纸上模拟一遍加法就明白了) 
       		if(num<10) {
       			res[i] = num;
       			break;
       		}else {
       			num = 0; 
       			res[i] = num;
       			takeOver = 1;
       		}	
       	}
       	
       	if(isTakeOver)
       		return;
       	
       	print(res);
       	
       }

   }
   
   //碰到第一个不为 0 的数才开始打印 
   public static void print(int[] res) {
   	
   	boolean isBegining0 = true; 
   	
   	for(int i = 0 ; i < res.length  ; i++) {
   		
   		if(isBegining0 && res[i] != 0 ) {
   			isBegining0 = false;
   		}
   		
   		if(!isBegining0) {
   			System.out.print(res[i]);
   		}
   		
   	}  
   	
   	System.out.print("\t");
   }

② 递归

/**
 * 剑指 Offer 17. 打印从1到最大的n位数
 * 将问题转化为数字的全排列问题(n个从 0 到 9 的全排列)
 * 递归全排列(递归代码更加简洁)
 * 输出函数不变
 */
public static void printNumbers(int n) {
	
	if( n<=0 ) return;
	
	int[] res = new int[n];
	
	for(int i = 0 ; i <= 9 ; i++) {
		res[0] = i;  //从第一个位置开始
		printNumbersRecursively(res , n , 0); // n 个 0 到 9 的全排列
	}
}

public static void printNumbersRecursively(int[] res, int n, int index) {
	
	//结束条件
	if(index >= (n - 1)) {
		print(res);
		return;
	}
	
	for(int i = 0 ; i <= 9 ; i++) {
		res[index+1] = i;
		printNumbersRecursively(res , n , index + 1 ); 
	}
	
}
	

看看测试啪,噢值太大了,电脑卡住了/(ㄒoㄒ)/~~
在这里插入图片描述
因为电脑限制,换个小点的测试数据啪(谁懂其中的痛……)
在这里插入图片描述
测试结果:n为5时,没有问题。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值