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

题目描述
输入数字n,按顺序打印出1到最大的n位十进制数,比如输入3,则打印1,2,3一直到最大的3位数即999

思路:看似很简单的一道题:

public static void Print1ToMaxOfDigits(int n){
        int number=1;
        for(int i=0;i<n;i++){
            number=number*10;
        }
        for(int j=1;j<number;j++){
            System.out.println(j);
        //上述代码存在问题,若n比较大,number可能会溢出,所以应考虑用字符串或者数组来存储
    }

先给出代码:

package com.su.biancheng;

import java.util.Arrays;

/**
 * @title Print1ToMaxOfDigits.java
 * @author Shuai
 * @date 2016-4-9下午4:22:24
 */
public class Print1ToMaxOfDigits {
    public static void Print1ToMaxOfDigits(int n){
        /*
        int number=1;
        for(int i=0;i<n;i++){
            number=number*10;
        }
        for(int j=1;j<number;j++){
            System.out.println(j);
        }
        */
        //上述代码存在问题,若n比较大,number可能会溢出,所以应考虑用字符串或者数组来存储

        if(n<=0)
            return;
        char[] number=new char[n];
        //初始化每个字符都为'0'
        for(int i=0;i<number.length;i++){
            number[i]='0';
        }
        while(!Increment(number)){
            PrintNumer(number);
        }
        //System.out.println(number);

    }
    private static void PrintNumer(char[] number) {
        //从第一个不为'0'开始打印
        boolean isBeginning0=true;
        for(int i=0;i<number.length;i++){
            if(isBeginning0&&number[i]!='0'){
                isBeginning0=false;
            }
            if(!isBeginning0){
                System.out.print(number[i]);
            }
        }
        System.out.println();

    }
    private static boolean Increment(char[] number) {
        boolean isOverFlow=false;
        int iTakeOver=0;
        for(int i=number.length-1;i>=0;i--){
            int iSum=number[i]-'0'+iTakeOver;
            if(i==number.length-1){
                iSum++;//如果是0999...999,加1,最高位由'0'变为1,据此可判断是否已经加到最大值
            }
            if(iSum>=10){
                if(i==0){
                    isOverFlow=true;
                    //break;可加可不加,因为此时已经循环结束
                }
                else{
                    iSum-=10;
                    iTakeOver=1;
                    number[i]=(char) ('0'+iSum);
                }
            }
            else{
                number[i]=(char) ('0'+iSum);
                break;
            }
        }
        return isOverFlow;
    }
    public static void main(String[] args){
        int n=3;
        Print1ToMaxOfDigits(n);
    }
}
Note:
while(!Increment(number)){
    PrintNumer(number);
}
解释一下以上代码,它的作用是为了检查是否已经加到最大数字。

Increment(number)
为什么不直接调用字符串比较函数equal来判断是否已经到99..99?
因为equal函数要逐个比较,对于n位数,时间为O(n),加上外层循环while,时间为O(n^2)

能否O(1)时间内完成比较?
如果已经是最大数字,则加上1后:最高位变为0(数组的第一位),同时产生数组越界的标志(就是进位了,这里字符数组长度为)


PrintNumer(number);
为什么不直接使用System.out.println(number);
使用System.out.println(number);则打印出的格式是00..01,00..02,..,不符合习惯。所以希望把没用的前面的0去掉。
每个数都是字符数组存储的,我们想从前往后遍历,找到第一个不为0,然后开始打印即可。

思路二:数字排列
算上需要前面补0的,n位数每一位都是0-9排列,这样可以使用递归的思想,先构造第一位,然后构造下一位,当构造到n位时,打印输出

/**
 * 
 */
package com.su.biancheng;

/**
 * @title Print1ToMaxOFDigits2.java
 * @author Shuai
 * @date 2016-4-9下午7:50:15
 */
public class Print1ToMaxOFDigits2 {
    public static void Print1ToMaxOFDigits2(int n){
        if(n<=0)
            return;
        char[] number=new char[n];
        /*for(int i=0;i<number.length;i++){
            number[i]='0';
        }*/
        Print1ToMaxOFDigitsRecursively(number,n,0);
    }

    private static void Print1ToMaxOFDigitsRecursively(char[] number, int n,
            int index) {
        if(index==number.length){
            PrintNumber(number);
            return;
        }
        for(int i=0;i<10;i++){
            number[index]=(char) (i+'0');
            Print1ToMaxOFDigitsRecursively(number,n,index+1);
        }

    }

    private static void PrintNumber(char[] number) {
        boolean isBeginning0=true;
        for(int i=0;i<number.length;i++){
            if(isBeginning0&&number[i]!='0'){
                isBeginning0=false;
            }
            if(!isBeginning0){
                System.out.print(number[i]);
            }
        }
        if(!isBeginning0){//00.000,不需要打印
            System.out.println();
        }

    }
    public static void main(String[] args){
        int n=3;
        Print1ToMaxOFDigits2(n);
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值