剑指Offer(12)-打印1到最大的n位数(考虑溢出问题)

题目:

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

方法1:

首先计算出n位数的最大十进制数,然后从1进行打印。

代码实现:
public class Solution {
  public void printToMaxOfNDigits(int n){
      if(n<=0){
          System.out.println("n输入错误")}
      long num=1;
      //找到最大数+1的值 如999 找到1000
      for(i=1;i<n;i++){
          num*=10;
      }
      for(long j=1;j<num;j++){
          System.out.println(j+" ");
      }
  }
}

方法2:

上面的代码考虑的问题很简单,默认为最大数值为long型,没有考虑长整型也会溢出的情况。故上面的代码鲁棒性很差。

鲁棒性好的思路:

因为上面分析可知我们在遇到比长整型还大的数时,上面的代码是不能成功执行的,即基本类型已经存储不下的数字。这时我们需要考虑用字符串或者数组来表示大数。

用字符串表示数字的时候,最直观的方法就是字符串里每个字符都是‘0’到‘9’之间的某一个字符,用来表示数字中的一位。因为最大的是n位的,因此我们需要一个长度为n+1的字符串(字符串中最后一个是结束符号‘\0’。当实际数字不够n位的时候,在字符串的前半部分补0)。

首先我们把字符串中的每一个数字都初始化为‘0’,然后每一次为字符串表示的数字加1,再打印出来。故我们只需要做两件事:一是在字符串表达数字上模拟加法,二是把字符串表达的数字打印出来。

在字符串表达数字上模拟加法,我们首先设置是否溢出标识,是否进位标识,以及取得字符数组长度,遍历这个字符数组,在末尾进行+1操作,如果末尾字符在+1后变为不小于10的数字,我们将末尾减去10加上‘0’字符赋值为末位,进位标识设置为1,在循环次位时+1,然后再判断是否为不小于10,是的话重复上面的步骤。直到判断高位是不是不小于10,是的话字符数组溢出;如果末尾字符在+1后是小于10的数字,直接加上‘0’赋值给末尾,跳出当前循环,返回没有溢出。

在字符串表达的数字打印出来方法时,没有什么特别,直接利用for循环遍历输出字符数组,但是要从高位第一个不是0的开始输出。

代码实现:
public class Solution {
  private void printNumber(char[] ch,int n){
      boolean begin=true;//最开始高位是不是0标志位
      for(int i=0;i<n;i++){
          //找到第一个不是0的位置,并开始打印
          if(begin&&ch[i]!='0'){
              begin=false;
          }
          if(!begin){
              System.out.print(ch[i]);
          }
      }
      System.out.println();
  }
  private boolean incrementNumber(char[] ch ,int n){
          boolean b=false; //是否溢出
          int nTack=0//是否进位
          for(int i=n-1;n>=0;i--){
              int num=ch[i]-'0'+nTack;
              //最低位直接自增
              if(i==n-1){
                  num++}
              //有进位
              if(num>=10){
                 //最高位有进位,产生溢出
                  if(i==0){
                      b=true;
                  }else{
                      //得到新的本位
                      num-=10;
                      //产生进位
                      nTack=1; 
                      ch[i]=(char)('0'+num);
                  }
              }else{
                  //不会在进行进位,
                  ch[i]=(char)num;
                  break;
              }
          }
      return !b;
  }  
  public void printToMaxOfNDigits(int n){
      if(n<=0){
          System.out.println("n输入错误")}
      char ch=new char[n];
      //初始化
      for(int i=0;i<n;i++){
          ch[i]='0';
      }
      //自增然后打印
      while(incrementNumber(ch,n)){
          printNumber(ch,n);
      }
  }
}

你可能感兴趣的:(剑指Offer)