统计数字问题
问题描述:
一本书的页码从自然数1开始顺序编码直到自然数n。书的页码按照通常的习惯编排,每个页码都不含多余的前导数字0。例如第6页用6表示而不是06或006。
数字统计问题要求对给定书的总页码,计算出书的全部页码中分别用到多少次数字0,1,2,3,.....9。
算法分析:
比如,对于一个数字34567,我们可以这样来计算从1到34567之间所有数字中每个数字出现的次数:
从0到9999,这个区间的每个数字的出现次数可以使用原著中给出的递推公式,即每个数字出现4000次。
从0到9999,这个区间的每个数字的出现次数可以使用原著中给出的递推公式,即每个数字出现4000次。
从10000到19999,中间除去万位的1不算,又是一个从0000到9999的排列,这样的话,从0到34567之间
的这样的区间共有3个。所以从00000到29999之间除万位外每个数字出现次数为3*4000次。然后再统计
万位数字,每个区间长度为10000,所以0,1,2在万位上各出现10000次。而3则出现4567+1=4568次。
之后,抛掉万位数字,对于4567,再使用上面的方法计算,一直计算到个位即可。
下面是自己的实现代码:
package abc; public class CountNum{ //递归求n位数中数字出现的次数 public static int count(int n){ if(n==1) return 1; else if(n<1) return 0; else return 10*count(n-1)+(int)java.lang.Math.pow(10,n-1); } public static int[] judge(int m){ int[] num = new int[10]; String str = m+""; int len = str.length(); int x = m; int y; int cs = (int)java.lang.Math.pow(10,len-1); //从高位到低位 for(int i=len-1;i>0;i--){ y = x/cs; for(int j=0;j<10;j++){ if(j<y) num[j] += y*count(i)+cs; else num[j] += y*count(i); } //去除多余的0的个数 num[0] -= cs; x = x%cs; num[y] += x+1; cs = cs / 10; } //最后到个位,每个数出现的次数 for(int i=0;i<=x;i++){ num[i]++; } return num; } public static void main(String[] args){ //System.out.print(count(9)); int[] s = judge(22); for(int i=0;i<s.length;i++) System.out.println(s[i]); } }