数字统计问题
2015-09-24 15:16
169 查看
1.问题描述
一本书的页码从自然数1开始顺序编码直到自然数n。书的页码按照通常的习惯编排,每个页码都不含多余的前导数字0。例如,第6页用数字6表示,而不是06或006等。数字计数问题要求对给定书的总页码n,计算出书的全部页码中分别用到多少次数字0,1,2,…,9。
2.算法设计
给定表示书的总页码的10进制整数n(1≤n≤109)。编程计算数的全部页码中分别用到多少次数字0,1,2,…,9。
3.数据输入
输入数据由文件名为input.txt的文本文件提供,每个文件只有1行,给出表示书的总页码的整数n。
4.结果输出
将计算结果输出到文件output.txt。输出文件共有10行,在第k行输出页码中用到数字k-1的次数,k=1,2,3,…,10。
5.求解问题的算法描述
{ 在一个n位十进制数的由低到高的第i位上,总是连续出现10^i个0, 10^i个1, ……, 10^i个9, 9之后又是连续的10^i个0, 10^i个1, ……, 10^i个9,这样循环出现。由此可以在第i位上求出每个数字出现的次数,而在第i个数位上,最前面的10^i个0是前导0,应该在统计的时候减掉。}
以上是我百度到的一段算法解析,没看太明白……
以下是我的分析:
我把页码看成是一个字符串,也就是 一个N位数 PageNum = AB…Z(其中0≤ A,B…,Z ≤9 ),比如A=a, B=b, …, C=c(0≤ a,b, … , z ≤9)
0.在A位置上:
number < a : count[number] += 10^(N-1);
number = a : count[number] += bc…z + 1;
number > a: count[number] += 0;
1.在B位置上:
number < b: count[number] += 10^(N-2) * (a+1);
number = b: count[number] += 10^(N-2) * a + (cd…z + 1);
number > b: count[number] += 10^(N-2) * a
2.在C位置上:
number < c: count[number] += 10^(N-3) * (ab+1);
number = c: count[number] += 10^(N-3) * (de…z + 1);
number > c: count[number] += 10^(N-3) * ab;
……
i.在I位置上:
number < i: count[number] += 10^(N-i-1) * (i前面的数字 + 1);
number = i: count[number] += 10^(N-i-1) * (i后面的数字 + 1);
number > i: count[number] += 10^(N-i-1) * i前面的数字;
[b]PS:以上计算的时候并没有讨论0的情况,而是把0006中0出现的次数一起统计了进去,因此在最后需要去掉前导0的计数![/b]
(思考这题的时候我其实是想从低位开始统计的,这样就可以不用考虑前导0 的问题,但是思考到一半还是换到了从高位开始,我想从低位开始找规律应该也是可行的,有空的时候我再从低位开始找规律的分析下)
(这个过程就像是小学时候的做奥数题,找规律一样~ 奥数题的话只要能找到规律算出答案就行了,但是算法呢还需要考虑得算法复杂度等,虽然不知道我写的算法算不算效率高的, 至少没有去一个一个数字遍历~)
6. 算法实现的关键技巧
在算法中要尤其注意每次循环中对最高位的计算,以及最后要减去前导0的个数。
7.实验分析及结论
以上就是我的第一题算法题~
希望自己可以坚持下去 :)
一本书的页码从自然数1开始顺序编码直到自然数n。书的页码按照通常的习惯编排,每个页码都不含多余的前导数字0。例如,第6页用数字6表示,而不是06或006等。数字计数问题要求对给定书的总页码n,计算出书的全部页码中分别用到多少次数字0,1,2,…,9。
2.算法设计
给定表示书的总页码的10进制整数n(1≤n≤109)。编程计算数的全部页码中分别用到多少次数字0,1,2,…,9。
3.数据输入
输入数据由文件名为input.txt的文本文件提供,每个文件只有1行,给出表示书的总页码的整数n。
4.结果输出
将计算结果输出到文件output.txt。输出文件共有10行,在第k行输出页码中用到数字k-1的次数,k=1,2,3,…,10。
5.求解问题的算法描述
{ 在一个n位十进制数的由低到高的第i位上,总是连续出现10^i个0, 10^i个1, ……, 10^i个9, 9之后又是连续的10^i个0, 10^i个1, ……, 10^i个9,这样循环出现。由此可以在第i位上求出每个数字出现的次数,而在第i个数位上,最前面的10^i个0是前导0,应该在统计的时候减掉。}
以上是我百度到的一段算法解析,没看太明白……
以下是我的分析:
我把页码看成是一个字符串,也就是 一个N位数 PageNum = AB…Z(其中0≤ A,B…,Z ≤9 ),比如A=a, B=b, …, C=c(0≤ a,b, … , z ≤9)
0.在A位置上:
number < a : count[number] += 10^(N-1);
number = a : count[number] += bc…z + 1;
number > a: count[number] += 0;
1.在B位置上:
number < b: count[number] += 10^(N-2) * (a+1);
number = b: count[number] += 10^(N-2) * a + (cd…z + 1);
number > b: count[number] += 10^(N-2) * a
2.在C位置上:
number < c: count[number] += 10^(N-3) * (ab+1);
number = c: count[number] += 10^(N-3) * (de…z + 1);
number > c: count[number] += 10^(N-3) * ab;
……
i.在I位置上:
number < i: count[number] += 10^(N-i-1) * (i前面的数字 + 1);
number = i: count[number] += 10^(N-i-1) * (i后面的数字 + 1);
number > i: count[number] += 10^(N-i-1) * i前面的数字;
[b]PS:以上计算的时候并没有讨论0的情况,而是把0006中0出现的次数一起统计了进去,因此在最后需要去掉前导0的计数![/b]
(思考这题的时候我其实是想从低位开始统计的,这样就可以不用考虑前导0 的问题,但是思考到一半还是换到了从高位开始,我想从低位开始找规律应该也是可行的,有空的时候我再从低位开始找规律的分析下)
(这个过程就像是小学时候的做奥数题,找规律一样~ 奥数题的话只要能找到规律算出答案就行了,但是算法呢还需要考虑得算法复杂度等,虽然不知道我写的算法算不算效率高的, 至少没有去一个一个数字遍历~)
6. 算法实现的关键技巧
在算法中要尤其注意每次循环中对最高位的计算,以及最后要减去前导0的个数。
7.实验分析及结论
public static void main(String[] args) { int page = 0; Scanner input; Formatter output; //读取页码数 try { input = new Scanner(Paths.get("input.txt")); if(input.hasNext()){ page = input.nextInt(); } input.close(); } catch (IOException e) { e.printStackTrace(); } //统计数字 int count[] = count(page); //写入文件 try { output = new Formatter("output.txt"); for(int num : count) output.format("%d%n", num); output.close(); } catch (FileNotFoundException e) { e.printStackTrace(); } } public static int[] count(int page){ //初始化计数数组 int count[] = new int[10]; for(int i = 0; i < 10; i++){ count[i] = 0; } //得出页码数的位/长度 String str = Integer.toString(page); int len = str.length(); int pre = 0;//前面最高位前面的数字 int now = 0;//当前的最高位 int rem = 0;//当前最高位后面的数字 for(int i = 0; i < len; i++){ rem = page % (int)(Math.pow(10.0, len-i-1)); now = page / (int)(Math.pow(10.0, len-i-1)); //计算小于当前最高位的数字在这个位置出现的次数 for(int j = 0; j < now; j++) count[j] += Math.pow(10.0, len-i-1) * (pre + 1); //计算当前最高位的数字在这个位置出现的次数 count[now] += Math.pow(10.0, len-i-1) * pre + rem + 1; //计算大于当前最高位的数字在这个位置出现的次数 for(int j = now + 1; j <= 9; j++) count[j] += Math.pow(10.0, len-i-1) * pre; //将当前最高位加到前面的数字中 pre = pre * 10 + now; //去掉当前最高位得到的数,也就是前面的余数 page = rem; } //去掉对前导0的计数 for(int i = 0; i < len; i++){ count[0] -= Math.pow(10.0, len-i-1); } return count; }
以上就是我的第一题算法题~
希望自己可以坚持下去 :)
相关文章推荐
- OGNL表达式struts2标签“%,#,$”
- bootstrap datetimepicker 插件语言选择
- 【思科】DHCP中继,三层交换VLAN间路由实战
- 块级元素和行内元素
- Android Intent中显示意图与隐式意图的基本用法
- canvas(2)绘制路径,文本,坐标变换
- UL下的LI用正则表达式替换样式
- Java学习笔记【静态域与静态方法】
- 站在OC的基础上快速理解Swift的类与结构体
- js弹出框、对话框、提示框、弹窗总结 .
- java 日期格式转换,加减等
- Java和C++通过Socket通信中文乱码的解决
- android隐藏软键盘
- 曾经山寨手机上的跨平台方案
- ubuntu 使用 github
- Android学习总结(一)
- leetcode3
- [LeetCode]Missing Number
- ios icon 尺寸
- sql语句中----删除表数据drop、truncate和delete的用法