30.从1到n的正数中1出现的次数

 

首先观察N=123456的情况:

十万位1的个数:    23456+1 = 23457

万位   1的个数:    (1+1)*10000 = 20000

千位   1的个数:    (12+1)*1000 =  13000

百位   1的个数:    (123+1)*100 = 12400

十位   1的个数:    (1234+1)*10 = 12350

个位   1的个数:    (12345+1)*1 = 12346

总数为:       93553

 

再看另一个N = 223456例子做比较:

十万位1的个数:    100000

万位   1的个数:    (2+1)*10000 = 30000

千位   1的个数:    (22+1)*1000 =  23000

百位   1的个数:    (223+1)*100 = 22400

十位   1的个数:    (2234+1)*10 = 22350

个位   1的个数:    (22345+1)*1 = 22346

总数为:       220096

 

以上结果和其他的方法求出来的结果相同,我们可以看出其中的一些规律:

在讨论某一个数位上的1的个数的时候,可以以这个数位为界,将原数一分为二,个人在编程时,还将给出的数字分为尾数为0和不为0:

如果尾数为0:

                  1、如果当前数位上的数字为1,则1出现的次数为当前数位后面的数+1,再加上当前数位前面的数乘以后面的基数;

                  2、如果当前数位上的数字为1,则1出现的次数为当前数位前面的-1,再乘以后面的基数;

如果尾数不为0:

                  1、当前数位前面的数(如果当前数位上的数为0,需减1),乘以后面的基数。

然而,数字的最高位应该要特殊处理:如果最高位是1(与123456类似),就是依照上述规律处理;如果最高位大于1,则是上述基数的值(与223456类似)。

 

以上是借鉴别人的思路,但总感觉有点不太好理解,我自已分析整理出自已的思路,写出代码:

如求123104

十万位1的次数:100000

万位1的次数    :(1+1)*10000

千位1的次数    :(12+1)*1000

百位1的次数    :(123)*100+(4+1)

十位1的次数    :(1231)*10

个位1的次数    :12310+1

思路: 求出整数十进制表示中1在每一位上出现的次数

             假设我们现在求一个整数任一一位上1出现的次数

            1.如果当前位==1

                     if当前位不是最后一位 num1=当前位前几位表示的整数*后面的基数+后面的几位表示的整数+1;

                     if当前位是最后一位,num1=当前位前几位表示的整数+1;

          2.如果当前位==0

                   if当前位不是最后一位,num1=当前位前几位表示的整数*后面的基数

                   if当前位是最后一位,num1=当前位前几位表示的整数

         3.如果当前位>1

                num1=(当前位前几位表示的整数+1)*后面的基数

代码如下

 

#include<iostream>

#include"string.h"

using namespace std;

 

int find_1(int n);

int num_of_1(int n)

{

        int count=0;

        for(int i=1;i<=n;i++)

               count+=find_1(i);

        return count;

}

 

int find_1(int n)

{

        int count=0;

        while(n>0)

        {

              

               if(n%10==1)

                       count++;

               n=n/10;

              

        }

        return count;

}

 

//上面是最直接的方法,时间复杂度为o(n)

//以下是第二种思路的代码

//两种方法验证得到的1出现的位数是相同的

 

 

int pow10(int n)

{

        int num=1;

        for(int i=0;i<n;i++)

               num=num*10;

        return num;

}

 

int num_of_1(int n)

{

        char *s=new char[50];

        int flag=0,count=0;

        sprintf(s,"%d",n);

        int size=static_cast<int>(strlen(s));

        for(int i=1;i<=size;i++)

        {

               //if('*s'<'0'||'*s'>9||'*s'=='\0')

               //      return count;

               cout<<*s<<endl;

               if(*s == '1')

               {

                       if(i==6)

                               count+=(flag+1);

                       else

                               count+=flag*pow10(size-i)+(atoi(s+1)+1);

                      

               }

               if(*s == '0')

               {

                       if(i==6)

                               count+=(flag);

                       else

                               count+=(flag)*pow10(size-i);

               }

 

               if(*s > '1')

                       count+=(flag+1)*pow10(size-i);

               flag=n/pow10(size-i);

               s=s+1;

        }

        return count;

}

 

int main()

{

        cout<<num_of_1(1304);

        cout<<"--------------"<<endl;

        cout<<num_of_1(1314);

        //cout<<"--------------"<<endl;

        //cout<<num_of_1(121);

       

 

       

       

}


 

                

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章