每天两道的目标已经被鸽了好几天了...我太难了
package cn.zxy.interview;
import org.junit.Test;
import java.util.Arrays;
/**
* 面试题17: 打印从1到最大的n位数
*
* 方法1: 关键点: 进位 溢出
* 方法2: 递归
*/
public class A17_PrintOneToMaxOfNDigits {
@Test
public void main(){
printOneToMax(3);
}
public void printOneToMax(int n){
if(n <= 0) return;
//1.字符数组保存要打印的数
char[] number = new char[n];
//2.初始化数组元素为'0'
Arrays.fill(number, '0');
while(!numberIncrement(number)){
printNumber(number);
}
}
/**
* 打印方法
* @param number
*/
private void printNumber(char[] number) {
//遇到第一个非零数字后 将flag置为true
//打印时先检查flag 只有是true才启动打印
boolean flag = false;
for (int i = 0; i < number.length; i++) {
if(!flag && number[i] != '0'){
flag = true;
}
if(flag){
System.out.print(number[i]);
}
}
System.out.println();
}
private boolean numberIncrement(char[] number) {
//1.溢出标志位
boolean isOverflow = false;
//2.需要往高位进位的数
int carryNum = 0;
//3.记录每次加和操作的临时变量
int sumTemp = 0;
//4.for循环从数组最后一位处理, 相当于在个位数进行加一
for (int i = number.length-1; i >= 0; i--) {
///对每一位取出-->与进位数相加
sumTemp = number[i] - '0' + carryNum;
if(i == number.length-1) sumTemp++;
//首位溢出则结束 其他位溢出进位
if(sumTemp >= 10){
if(i == 0){
isOverflow = true;
}else{
sumTemp -= 10;
carryNum = 1;
number[i] = (char)(sumTemp + '0');
}
}else{
number[i] = (char)(sumTemp + '0');
return isOverflow;
}
}
return isOverflow;
}
// 递归方法
/*
用递归的方法设置每一位, 第一次递归到最深, 然后从最深处加1, 最深一层循环完后, 回退一层, 次深层加一后, 再进入最深一层
结束条件: 递归深度为数字位数+1
注意这里递归深度的边界容易容错 因为我们是在边界条件中打印, 因此到达边界时, 三位数已经设置好了, 也就是说, 这时候index应该自增长为3了
而index=3已经是尽头, 不会再进行for循环, 而是直接返回到index=2, 进行个位的自增
增长完后进入边界, 打印, 返回, 以此类推...
*/
@Test
public void recMain(){
int N = 3;
char[] number = new char[N];
//初始化为0
Arrays.fill(number, '0');
printOneToMaxRec(number, 0);
}
public void printOneToMaxRec(char[] number, int index){
//System.out.println(index + "层开始...");
if(index == number.length) {
printNumber(number);
return;
}
for(int i = 0; i < 10; i++){
number[index] = (char)(i + '0');
printOneToMaxRec(number, index+1);
}
}
}
网友评论