打印1到最大的n位数

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

这道题目看着很简单,最简单的思想就是先求出最大的n位数,然后用一个循环从1开始逐个打印,代码很简单:

void Print1ToMaxOfNDigits_1(int n)
{
   int number=1;
   int i=0;
   while(i++<n)
   {
     number*=10;
   }
   for(i=i;i<number;i++)
   {
      printf("%d\t",i);
   }
}

初看之下似乎没什么问题,但如果仔细分析这个问题,当输入的n很大的时候,我们求最大的n位数是不是用整形(int)或者长整形(long long)都会溢出?在这里我们没有考虑大数问题。

思路:我们可以用字符串或者数组来表达大数。用字符串表示数字的时候,最直观的方法就是字符串里面每个字符都是’0’到’9’之间的某个字符,用来表示数字中的一位。因为数字最大是n位,因此我们需要一个长度为n+1的字符串(字符串中最后一个是结束符号’\0’),当实际数字不够n位时,在字符串的前半部分补0。首先我们把字符串中的每一个数字都初始化为’0’,然后每一次为字符串表示的数字加1,再打印出来。

即分为两步:1.在字符串表达的数字上模拟加法 2把字符串表达的数字打印出来

void Print1ToMaxOfNDigits(int n)
{
    if(n<0)
    {
       return;
    }
    char *number=new char[n+1];
    memset(number,'0',n);
    number[n]='\0';
    while(!Increment(number))//字符串没有溢出
    {
      PrintNumber(number);//打印数字
    }
    delete []number;
}


bool Increment(char *number)
{
    bool isOverflow=false;
    int  nTakeOver=0;
    int  nLength=strlen(number);
    for(int i=nLength-1;i>=0;i--)//从最后一个数字开始
    {
        int nSum=number[i]-'0'+nTakeOver;//得到最一位数值
        if(i==nLength-1)
        {
           nSum++;//数字+1
        }
        if(nSum>=10)//值>=10要进位*******************
        {
            if(i==0)//如果已经到了第一位,进位就溢出
            {
                isOverflow=true;
            }
            else{//如果没有到第一位,就向前进位
                nSum-=10;//该位变为0,进一位
                nTakeOver=1;//进位+1
                number[i]='0'+nSum;
            }
        }
        else{//值<10,结束,准备打印该值***************
           number[i]='0'+nSum;
           break;
        }  

    }
    return isOverflow;
}


void PrintNumber(char *number)
{
   bool isBeginning0=true;
   int nLength=strlen(number);
   for(int i=0;i<nLength;i++)
   {
      if(isBeginning0 && number[i]!='0')//只有碰到第一个非0字符之后才开始打印
      {
          isBeginning0==false;
      }
      if(!isBeginning0)
      {
          printf("%c",number[i]);
      }
   }
   printf("\t");
}

上述思路虽然很直观,但是由于模拟了整数的加法,代码看起来有些冗长。下面我们换一种思路来考虑这个问题。如果我们在数字前面补0的话,就会发现n位所有十进制数其实就是n个从0到9的全排列。全排列用递归很容易,数字的每一位都可能是0到9中的一个数,然后设置下一位

void Print1ToMaxOfNDigits(int n)
{
   if(n<=0)
   {
      return;
   }
   char* number=new char[n+1];
   number[n]='\0';
   for(int i=0;i<10;++i)
   {
     number[0]=i+'0';
     Print1ToMaxOfNDigitsRecursively(number,n,0);
   }
   delete[] number;
}


void Print1ToMaxOfNDigitsRecursively(char* number ,int length,int index)
{
   if(index==length-1)
   {
      PrintNumber(number);
      return;
   }
   for(int i=0;i<10;++i)
   {
      number[index+i]=i+'0';
      Print1ToMaxOfNDigitsRecursively(number,length,index+1);
   }
}

void PrintNumber(char* number)
{
   int nLength=strlen(number);
   bool isBeginning0=true;
   for(int i=0;i<nLength;++i)
   {
      if(isBeginning0 && number[i]!='0')
      {
          isBeginning0=false;
      }
      if(!isBeginning0)
      {
          printf("%c",number[i]);
      }
   }
}
  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值