11 统计数字问题

最近学习算法设计与分析,老师推荐王晓东的计算机算法设计与分析,感觉真的很不错,但是第一到算法实现题就给难住了,题目如下(后来发现编程之美上也有这个题目,只是让求1出现的次数):

一本书的页码从自然数1开始顺序编码直到自然数n。每个页码不包含多余的前导数字0.给定书的总页码,计算出书的全部页码中分别用到多少次数字0,1,2,。。。9.
一下子能想到的笨方法就是遍历1到n之间的每个数字,统计每个页码数中每个数字出现的次数,这样非常慢。

代码如下:

#include <stdio.h>
#include <time.h>

int countInteger(int m)
{
int num = 0;
while(m != 0) {
num += (m % 10 == 1) ? 1 :0;
m /= 10;
}
return num;
}
int main()
{
int n,i;
int count = 0;
scanf("%d", &n);
double start = (double)clock();
for (i = 1; i <= n; i++) {
count += countInteger(i);
}
double finish = (double)clock();
printf("%d\ntime = %.20fms\n", count, (finish - start)/1000);
return 0;
}

参考编程之美的方法后可改进下:

假设给定总页码为N=abcde,当前处理到c,即统计百位上每个数字出现次数,则具有如下规律:
如果要统计百位上数字i出现的次数(i=0,1,2,3,...9),其实它受到三个因素的影响:百位上的数字(curnum),百位以下的数字(lownum),百位以上的数字(hignum).
如果百位上数字c>i则:sum[i]+=(hignum+1)*fact,其中sum[i]表示百位上出现i的次数,hignum=ab,fact表示当前处理到的位的基数,百位时fact=100,十位时fact=10,个位时fact=1;
如果百位上数字c=i则:sum[i]+=hignum*fact+lownum+1,此处hignum=ab,lownum=de
如果百位上数字c<i则:sum[i]+=hignum*fact; 此处hignum=ab
另外,
000 
001
....(9)
009
010
....(90)
099
100
....(900)
999
需要去掉这写开头是0的数字中多余的0,当n的数字长度为len时,多余的0的个数为,
len=1时为0+1个
len=2时为1*9*10^0+2个
len=3时为9*10^1+2*9*10^0+3个
...
len=k时为9+99+999+...+99..99(k个9)+k个
 

因此代码如下:

#include <stdio.h>
#include <math.h>
#include <time.h>

/**int power(int x, int y)
{
int i;
int s = 1;
for (i = 0; i < y; i++) {
s *= x;
}
return s;
}**/
int sum(int n)
{
int sum[10] = {0};
int hignum = 0;
int lownum = 0;
int curnum = 0;
int fact = 1;
int i;
int len = 0, zero = 0;

while (n / fact != 0) {
lownum = n - (n / fact) * fact;
curnum = (n / fact) % 10;
hignum = n / (fact * 10);
for (i = 0; i < 10; i++) {
if (curnum > i) {
sum[i] += (hignum + 1) * fact;
}
else if (curnum == i) {
sum[i] += hignum * fact + lownum + 1;
}
else {
sum[i] += hignum * fact;
}
}
fact *= 10;
len++;
}
for (i = 0; i < len; i++) {
zero += (len - i - 1) * 9 * pow(10*1.0, i*1.0) * 1.0;
}
zero += len;
sum[0] -= zero;
for (i = 0; i < 10; i++) {
printf("%d : %d\n", i, sum[i]);
}
}

int main()
{
int n;
while(scanf("%d", &n) != EOF) {
sum(n);
}
return 0;
}

注:以上内容出于学习目的,借鉴他人之处,未经允许,经请谅解。

原文地址:https://www.cnblogs.com/taotao315/p/2950764.html