legend

思考助我前行

1的个数

1.    1的个数............................................................................................................... 1

 

1.    1的个数

给定一个十进制正整数N,写下从1开始,到 N的所有正数,然后数出其中出现所有1的个数。

常规方法:学过c的几乎都能编出来这种双重循环的程序

#include "stdio.h"

#include "math.h"

#include "time.h"

int main()

{

     clock_t c1,c2;

     c1=clock();

     int N;

     int i,j;

     N=1234567;

     int count=0;

     for(i=1;i<=N;i++)

     {

         j=0;

         while(i/(int)pow((double)10,(double)j))

         {

              if(((i/(int)pow((double)10,(double)j))%10)==1)

                   count+=1;

              j++;

         }

     }

     printf("the number of 1 is %d/n",count);

     c2=clock();

     printf("the run time is %d/n",c2-c1);

 

}

改进算法:

描述:将求值分为不同位数上分别求1的个数,最后累加。

比如1234567,要求百位上出现1的数的个数,即cal12345673),要先求出百位之前的数1234,即front(1234567,3),再求百位之后的数67,back(1234567,3).不难看出百位上的数5,即on12345673)是关键。他为01,和其他的时候对应不同的结果,这也此题最重要的规律和算法,实现在cal()中。

 

#include "stdio.h"

#include "math.h"

#include "time.h"

int num(int a) //return how many numbers the a has

{

     int i=0;

     while(a/(int)pow((double)10,(double)i))

         i++;

     return i;

}

int front(int a,int k) //return the number in front of the kth.

{

     return a/(int)pow((double)10,(double)k);

}

int back(int a,int k) //return the number back kth.

{

     return a%(int)pow((double)10,(double)(k-1));

}

int on(int a,int k) //return the number in the kth.

{

     return a/(int)pow((double)10,(double)(k-1))%10;

}

int cal(int a ,int k) //return the number of 1 in the kth

{

     int p;

     p=on(a,k);

     if(p==0)

     {

         return front(a,k)*(int)pow((double)10,(double)(k-1));

     }

     else if(p==1)

     {

         return front(a,k)*(int)pow((double)10,(double)(k-1))+back(a,k)+1;

     }

     else

     {

         return (front(a,k)+1)*(int)pow((double)10,(double)(k-1));

     }

}

int cal_all(int a) //return all 1 in the a

{

     int i;

     int count=0;

     for(i=1;i<=num(a);i++)

     {

         count+=cal(a,i);

     }

     return count;

}

int main()

{

     clock_t c1,c2;

     c1=clock();

     int N=1234567;

    printf("all the 1 in N is %d/n",cal_all(N));

     c2=clock();

     printf("the run time is %d/n",c2-c1);

    

}

运行时间不知道算是提高了多少倍。。。

 

Ps:经测试用了math.h里的pow函数和不用pow函数效率相差一个数量级。所以程序设计时,不要为了方便盲目的调用其他库函数。因为link过程比较费时。以下是不用pow函数的实现:

#include "stdio.h"

#include "time.h"

#define time_test 1

int main()

{

     #ifdef time_test

     clock_t c1,c2;

     c1=clock();

     #endif

     int N;

     int i,j;

     N=1234567;

     int count=0;

     for(i=1;i<=N;i++)

     {

         j=i;

         while(j!=0)

         {

              if(j%10==1)

                   count++;

              j/=10;

         }

     }

     printf("the number of 1 is %d/n",count);

     #ifdef time_test

     c2=clock();

     printf("the run time is %d/n",c2-c1);

     #endif

 

}

而且同样的程序在gcc中能够更高效,体现了一般情况gccvc效率的对比

阅读更多
个人分类: algorithm
想对作者说点什么? 我来说一句

求合法值为1,2,3

2013年04月10日 935B 下载

特殊数字求和(java)

2011年06月04日 12KB 下载

没有更多推荐了,返回首页

加入CSDN,享受更精准的内容推荐,与500万程序员共同成长!
关闭
关闭