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

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

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

package algorithm.foroffer.top20;

import java.math.BigInteger;
import java.util.Arrays;

/**
 * Created by liyazhou on 2017/5/25.
 * 面试题12:打印 1 到最大的 n 位数
 *
 * 题目:
 *      输入数字 n,按顺序打印出从 1 最大的 n 位十进制数。
 *      比如输入 3,则打印出 1,2,3 一直到最大的 3 位数即 999.
 *
 * 问题:
 *      1. 大整数问题
 *
 * 思路:
 *      1. 使用 BigInteger类型
 *      2. 使用整型数组模拟大整数以及加 1 运算
 *             数组的左端表示整数的高位,右端表示整数的低位
 *             每次为该"整数"加1,
 *                  如果高位没有溢出,打印该整数
 *                  否则,停止循环加1的操作
 *             打印出整数的合理形式
 */
public class Test12 {

    public static void printOneToNDigits(int length){
        if (length < 0) throw new RuntimeException("Invalid input.");

        BigInteger max = BigInteger.TEN.pow(length);
        for(BigInteger i = BigInteger.ONE; i.compareTo(max) < 0; ){
            System.out.print(i.toString() + "\t");
            i = i.add(BigInteger.ONE);
        }
    }


    /**
     * 思路:
     *      1. 使用数组模拟大整数,数组左端为高位,右端为低位
     *      2. "数字"每次增加 1,
     *          如果没有溢出,也即是最高位没有进位时,打印出用数组表示的该数字;
     *          否则,退出循环
     *
     * @param length 最大数字的位数
     */
    public static void printOneToNDigits2(int length){
        if (length < 1) throw new RuntimeException("Invalid input, the parameter must be bigger than 0");
        // 存储大整数
        int[] arr = new int[length];
        while(!addOne(arr)){
             // System.out.println(Arrays.toString(arr));
             printDigit(arr);
        }
    }

    /**
     * 功能:打印用数组表示的整数
     * 思路:判断开头是不是连续的0,如果是,则忽略;遇见非零元素后,打印后面的全部元素
     * @param arr 表示"整数"的数组
     */
    private static void printDigit(int[] arr) {
        boolean isZero = true;
        for (int i = 0; i < arr.length; i++){
            if (isZero && arr[i] != 0) isZero = false;  //遇见非零数字后,不会再执行该语句
            if (!isZero)  System.out.print(arr[i]);
        }
        System.out.print("\t");
    }

    /**
     * 用数组模拟大整数加法运算,并判断"整数"加 1 后最高位是不是进位
     *
     * @param arr 表示"整数"的数组
     * @return 最高位是否进位
     */
    private static boolean addOne(int[] arr) {
        int increment = 1;
        boolean isOverflow = true;
        for(int i = arr.length-1; i >=0; i--){
            int digit = arr[i] + increment;
            increment = digit / 10;
            arr[i] = digit % 10;
            if (increment == 0) {
                isOverflow = false;
                break;
            }
        }
        return isOverflow;
    }


    public static void printOneToNDigits3(int length){

    }


    public static void main(String[] args){
        Test12.printOneToNDigits(2);
        System.out.println();
        Test12.printOneToNDigits2(2);
    }
}

2017-9-16 18:40:35

 /**
  * 连续打印1~length位的所有整数(比之前版本更容易理解)
  * @param length 最大整数的位数
  */
 public void test12_printOneToN02(int length){
     // 如果length = 3,则最大值是 1000,最高位是 1 则退出循环
     int[] arr = new int[length + 1];
     while(test12_addOne(arr)){  // 如果最高位不是 1, 则一直加 1
         test12_printN(arr);  // 打印当前的整数
     }
 }

 private void test12_printN(int[] arr) {
     boolean isZero = true;
     for (int i = 0; i < arr.length; i ++){
         if (arr[i] != 0) isZero = false;  // 遇到非零数字之前,isZero = true,则将不会执行下面的打印语句
         // if (isZero && arr[i] != 0) isZero = false;  
         // 小优化,只有isZero=true时,才可能执行该语句,为false时一定不会执行
         if (!isZero) System.out.print(arr[i]);
     }
     System.out.print("\t");
 }

 /**
  * 如果最高位不是1,返回true,表示还没有达到最大值,可以继续加 1
  * @param arr 使用数组保存整数
  * @return 是否可以继续加 1
  */
 private boolean test12_addOne(int[] arr) {
     int increment = 1;
     // 模拟整数加 1 操作
     for (int i = arr.length-1; i >= 0; i--){
         int intDigit = arr[i] + increment;
         arr[i] = intDigit % 10;
         increment = intDigit / 10;
         if (increment == 0) break;
     }
     // 判断最高位是否为 1
     boolean continues = true;
     if (arr[0] == 1) continues = false;
     return continues;
 }
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值