算法:统计数字问题的两种解法

    科技2022-07-29  109

    一、问题描述:

    统计数字问题:一本书的页码从自然数1开始顺序编码直到自然数n。书的页码按照通常的习惯编排,每个页码都不含多余的前导数字0。例如,第6页用数字6表示,而不是06或006等。数字计数问题要求对给定书的总页码n,计算出书的全部页码中分别用到多少次数字0,1,2,…,9.

     

    二、算法描述:

    解法一:直接一位一位的取,一个一个的求。 start 输入页码数n值 定义整数count决定循环的进程 定义整数数组a,长度为10用来统计出现的0,1,2,,,9次数 //刚好可以利用下标进行统计 for(count=1 ; count<=n ; count++){ 定义整数s,用于接收count的值 for( ; s!=0 ; s=s/10){ 定义整数flag,用于接收每一次从s中分离出来的数字 flag = s ; a[flag]++; } } //建立一个循环用于输出结果 定义整数 i,用于对流程的控制 for(i=0 ; i<=9 ; i++){ 输出:数字 i 出现的次数为a[i] } End 解法二:利用这个规律——由0,1,2,····9组成的所有n位数。从n个0到n个9一共有10n个n为数。在这10n个n位数中,0,1,2,····9每个数字使用的次数相同,设为f(n)。f(n)=n10n-1。后面再去掉多算的零。 Start 输入页码数n值 利用count函数计算未处理之前的0~9出现的个数情况并存在num数组中 利用delete函数计算多计算0出现的个数 输出最后的结果 输入 End 整数 Delete(输入总页码数n的位数){ 定义整数变量sum用于累加 for(int i = n的位数;i大于等于1;i减一){ sum+=(int)Math.pow(10,i-1); } return sum; } void count(输入总页码数n的值){ //分组批次处理 for(int i = 0;i<10;i++) { num[i] += n的首位*n的长度减一*10的n的长度减二的次方 } //首位的处理 for(int i=0;i<n的首位;i加一){ num[i]+= 10的n的长度减1的次方 } //余数最高位出现的次数+整数的情形 num[n的首位]+=n的余数加一 //对余数进行处理 //情况一:余数为零 if(n的余数为零){ num[0]+=n的长度减一 return } //情况二:余数不为零,但是余数和最高位之间夹着零 if(n的长度减一!=余数的长度){ num[0]+=(余数-1-余数的长度)*(余数加一) } //情况三:正常情况 count(n的余数) }

     

    三、代码求解:

    解法一:直接一位一位的取,一个一个的求。 import java.util.*; public class MyCount { public static void main(String args[]) { Scanner sc = new Scanner(System.in); int n = sc.nextInt(); int[] a = new int[10]; int count;//用于遍历循环 int s;//用于接收count的值 for(count=1;count<=n;count++) { s=count; for (int flag;s!=0;s=s/10) { flag = s; a[flag]++;//计数 } } //建立一个循环用于输出结果 for (int i=0;i<10;i++) { System.out.println("数字"+i+"出现的次数为"+a[i]); } } } 解法二:利用这个规律——由0,1,2,····9组成的所有n位数。从n个0到n个9一共有10n个n为数。在这10n个n位数中,0,1,2,····9每个数字使用的次数相同,设为f(n)。f(n)=n10n-1。后面再去掉多算的零。 import java.util.*; public class MyCount { public static int num[] = new int[10]; public static void main(String args[]) { //接收输入 Scanner sc = new Scanner(System.in); //转换为数字接收 int n = 0; n = sc.nextInt(); //利用Count函数计算未处理之前的计数 count(n); //减去多算的0的个数 num[0] -= delete(getLength(n)); //打印结果 for(int i = 0;i<10;i++) { System.out.println(num[i]); } } //删除多余的数字个数 public static int delete(int length) { int sum = 0; //这里利用的是多加0的增长规律,譬如1~10,多算了10个0,1~100多算了100个0 for(int i = length;i>=1;i--) { sum+=(int)Math.pow(10, i-1); } return sum; } //获得数字的长度 public static int getLength(int num) { return (int)Math.log10(num)+1; } //获得数字的首位 public static int getHead(int num) { return num/(int)Math.pow(10, getLength(num)-1); } //获得数字除去最高位后的余数 public static int getRemainder(int num) { return num%(int)Math.pow(10, getLength(num)-1); } //计算数字的总数 public static void count(int n) { //分组处理,这个规律是推出来的 for(int i = 0;i<10;i++) { num[i] = num[i]+getHead(n)*(getLength(n)-1)*(int)Math.pow(10, getLength(n)-2); } //首位的处理 for(int i = 0;i<getHead(n);i++) { num[i] += (int)Math.pow(10, getLength(n)-1); } //余数最高位出现的次数+整数情形 num[getHead(n)]+=getRemainder(n)+1; //判断余数的情况 //情况一:余数为零,加最大的整数的后长度减一个的0 if(getRemainder(n)==0) { num[0]+=getLength(n)-1; return; } //情况二:余数不为零,但是余数和最高位之间夹着零,夹了几个*余数的个数 if(getLength(n)-1!=getLength(getRemainder(n))) { num[0]+=(getRemainder(n)-1-getLength(getRemainder(n)))*(getRemainder(n)+1); } //情况三:正常情况,递归进行 count(getRemainder(n)); } }

    Ending... ...

    Processed: 0.010, SQL: 8