页码数字统计问题(数字统计问题)

  • 问题描述
  • 算法思路与实现代码
    • 方法一:暴力遍历法
    • 代码1
    • 方法二:拆数计算法
    • 代码2
  • 代码测试
  • 算法复杂度分析

问题描述

一本书的页码从自然数1开始顺序编码直到自然数n。书的页码按照通常的习惯编码,每个页码都不含有多余的前导数字0。现在给出表示书的总页码的自然数n,计算书的全部页码中分别用到多少次数字0,1,2,3,…, 9。(或者计算说0-9数字出现了多少次)。

例如,给出一个数n=12,则出现的数有1,2,3,4,5,6,7,8,9,10,11,12。这些数中0-9分别出现的次数为:(由上到下分别表示0-9出现的次数,后文程序结果都采用这样的格式)

题目源于:王晓东.《计算机算法设计与分析》.第5版习题1-1

算法思路与实现代码

方法一:暴力遍历法

思路:设置一个长度为10的数组作为0-9每个数出现次数的计数器,将页码从1~n遍历一遍,提取每一个数的每一位,根据每一位数的值给对应数字计数器加1,最后在循环结束后通过计数器内的结果确定每个数字的出现次数。

代码1

#include<stdio.h>
int main(){int arr[10]={0};//存储0-9各个数的出现次数,初始化为零int n; scanf("%d",&n);//输入nfor(int i=1;i<=n;i++){//拆分每一个数的每一位int num[10]={0};//存每次数的每一位的值 int len=0; //这个数的位数 int m = i;while(m/10){//采用除10取余的方式,从个位开始获取每一位的值num[len++] = m%10;m = m/10;}num[len++] = m;for(int j=0;j<len;j++){//对应计数器+1arr[ num[j] ]++;}}for(int i=0;i<10;i++){//打印结果printf("%d\n",arr[i]);}
return 0;
}

方法二:拆数计算法

思路:统计0-9每个数,分别在每一位上的出现次数。即对于一个总位数为len的数n,依次计算其第一位(个位),第二位(十位),第三位…,第len位上,0-9每个数出现的次数,再统计每次的计算结果。

每一位上各个数字出现的次数与四个条件有关:这一位上的数的值V(Value),这一位数前面一串数的值F(Front),这一位数后面一串数的值R(Rear),这一位数的位置P。以n=12345的第三位(百位)为例,这一位上0-9各个数出现的个数分别与:V=3,F=12,R=45,P=3.有关。
对于输入数n,其任意位都有VFRP(对于最高位,取F=0;对于第一位,取R=0),考虑其任意一位,有如下四种规则:
① 0 − 9 各 数 在 该 为 的 出 现 次 数 至 少 为 : F × 1 0 P − 1 ② 对 于 0 − 9 中 大 于 V 的 数 , 出 现 次 数 不 必 额 外 增 加 。 ③ 对 于 0 − 9 中 等 于 V 的 数 , 出 现 次 数 与 还 R 有 关 , 需 加 上 : R + 1 ( 0 到 x , 共 有 x + 1 个 数 ) ④ 对 于 1 − 9 中 小 于 V 的 数 , 需 加 上 : 1 0 P − 1 \begin{aligned} ①&0-9各数在该为的出现次数至少为:F×10^{P-1}\\ ②&对于0-9中大于V的数,出现次数不必额外增加。\\ ③&对于0-9中等于V的数,出现次数与还R有关,需加上:R + 1(0到x,共有x+1个数)\\ ④&对于1-9中小于V的数,需加上:10^{P-1} \end{aligned} ①②③④​0−9各数在该为的出现次数至少为:F×10P−1对于0−9中大于V的数,出现次数不必额外增加。对于0−9中等于V的数,出现次数与还R有关,需加上:R+1(0到x,共有x+1个数)对于1−9中小于V的数,需加上:10P−1​
第四点中不包括0,是因为0不可出现在首位,即没有0,024,0324等数,例如当n=123,考虑P=2(十位),在已考虑①的前提下,考虑④,显然当1<2,1出现的次数需要额外加10(因为有10,11,12,…,20的过程);而对于0<2,0出现的次数不能加10(因为没有00,01,02,…,10的过程,只有1,2,3,4…,10,在这个过程十位没有出现0)。

所以只需要得到n每一位上的VFRP,再设置一个长度为10的数组作为0-9每个数出现次数的计数器,循环计算并统计各个位上每个数的出现次数,最后通过计数器内的结果确定每个数字的出现次数。

代码2

#include<stdio.h>
int main(){int arr[10]={0};//保存每一个数出现次数的计数器数组 int pow10[10]={1};  //每一位的权值,即10^(P-1)for(int i=1;i<10;i++)pow10[i]=10*pow10[i-1];int n; scanf("%d",&n); //输入nint num[3][10]={0};//[0]存每一位的值V//[1]存每一位前面一串数的值F//[2]存每一位后面一串数的值R int len=0; //记录位数 Pwhile(n/10){ // 拆分n的每一位,获取VFRnum[0][len] = n%10;num[2][len+1] += n%10*pow10[len] + num[2][len];n = n/10;num[1][len++]=n;}num[0][len++] = n;int i = 0; for(i=0;i<len;i++){ for(int j=0;j<10;j++){arr[j] += num[1][i]*pow10[i]; //对于0-9中等于V的数,出现次数与还R有关,需加上:R + 1if(j==num[0][i]){arr[j] += num[2][i] + 1;}// 对于1-9中小于V的数,需加上:10^(P-1)else if(j<num[0][i] && j!=0){ arr[j] += pow10[i];}}}for(int i=0;i<10;i++)printf("%d\n",arr[i]);
return 0;
}

代码测试

测试用例1:12345

测试用例2:45678

算法复杂度分析

方法一:
此算法一共包括三个核心循环,最外层大循环1 ~ n 需要循环n次。大循环内有两个小循环顺序执行,一个循环是提取每个数的每一位,循环次数由每次被提取数的位数决定,而被提取数的最大位数不大于 log ⁡ 10 n \log_{10} n log10​n;第二个循环是根据提取的每一位,给对应计数器+1,循环次数也由被提取数的位数决定,即不大于 log ⁡ 10 n \log_{10} n log10​n,所以程序总的时间复杂度为O ( 2 log ⁡ 10 n ⋅ n 2\log_{10} n · n 2log10​n⋅n), 即O ( n ⋅ log ⁡ 10 n n·\log_{10}n n⋅log10​n)。

方法二:
此算法一共包括三个核心循环,第一个循环拆分n的每一位,并求各种值,一共循环 log ⁡ 10 n \log_{10} n log10​n次;第二个循环逐位计算每一位上出现各种数的次数,共循环 log ⁡ 10 n \log_{10} n log10​n次,其内嵌套着第三个循环,计算从0-9各个数的具体出现次数,共循环10次。所以程序总的时间复杂度为O( log ⁡ 10 n + 10 log ⁡ 10 n \log_{10} n + 10\log_{10} n log10​n+10log10​n ),即O( log ⁡ 10 n \log_{10} n log10​n)。

分享的同时记录自己的学习,感谢阅读,有问题还请交流指正。^ ^

页码数字统计问题(数字统计问题)相关推荐

  1. 统计0-n数字中出现k的次数

    /*** 统计0-n数字中出现k的次数,其中k范围为0-9 */ public static int countOne(int k, int n) {if (k > n) {return 0;} ...

  2. 使用函数统计指定c语言,浙大版《C语言程序设计(第3版)》题目集 习题5-5 使用函数统计指定数字的个数...

    热门文章推荐 以下50道算法编程题访问量较大,包含常用语法,数据结构,解题思路等等,作为C语言学习者必练题目推荐给各位.创作不易,记得一键三连哦!!! 习题5-5 使用函数统计指定数字的个数 本题要求 ...

  3. 6-9 统计个位数字 (15 分)

    6-9 统计个位数字 (15 分) 本题要求实现一个函数,可统计任一整数中某个位数出现的次数.例如-21252中,2出现了3次,则该函数应该返回3. 函数接口定义: int Count_Digit ( ...

  4. 统计一个数字在排序数组中出现的次数

    package demo;import java.util.Arrays;/** 题目描述 统计一个数字在排序数组中出现的次数.*/ public class Offer_23 {public int ...

  5. c语言 统计数量用count_c语言中统计重复数字次数 c语言问题 统计不同数字的个数...

    请问c语言当中,如何统计数字各自出现的次数 请教一个问题: 在c语言当中,用数组的方法,统计输入的一串数字,统计实现代码: #include int main() { int num = 0, i = ...

  6. 输入一个字符串,对字符中的各个英文字符,数字,空格进行统计。 按照统计个数由多到少输出统计结果,如果统计的个数相同,则按照ASII码由小到大排序输出

    题目描述: 输入一个字符串,对字符中的各个英文字符,数字,空格进行统计.按照统计个数由多到少输出统计结果,如果统计的个数相同,则按照ASII码由小到大排序输出. 输入描述:输入一串字符. 输出描述:对 ...

  7. 分别统计其中数字、英文字母和其它字符的个数

    从键盘输入20个字符,存放在一个字符数组中,然后分别统计其中数字.英文字母和其它字符的个数.( 其中字母在字符的值在65 – 90,97 – 122 为字母,字符 #include<stdio. ...

  8. 使用函数统计指定数字的个数 (15 分)

    使用函数统计指定数字的个数 (15 分) 本题要求实现一个统计整数中指定数字的个数的简单函数. 函数接口定义: int CountDigit( int number, int digit ); 其中n ...

  9. C语言:浙大版《C语言程序设计(第3版)》题目集 习题5-5 使用函数统计指定数字的个数 (15 分)

    其他题目详见:浙大版<C语言程序设计(第3版)>题目集 一.题目描述: 习题5-5 使用函数统计指定数字的个数 (15 分) 本题要求实现一个统计整数中指定数字的个数的简单函数. 函数接口 ...

  10. word怎么显示计算机数字,如何使word文档自动显示字数统计 Word自动统计文档字数在哪里...

    如何使word文档自动显示字数统计 Word自动统计文档字数在哪里 Word中有一个非常实用的字数统计功能,如要统计一个文档中的字数,直接在菜单栏中单击"审阅→字数统计",便可得到 ...

最新文章

  1. python3各版本区别-Python2 与Python3的版本区别实例分析
  2. 强化学习note1——马尔科夫奖励过程MRP和马尔科夫决策过程MDP各个函数的定义与区别
  3. linux运维常用命令一句话
  4. julia有 pytorch包吗_用 PyTorch 实现基于字符的循环神经网络 | Linux 中国
  5. 2019-03-4-算法-进化(罗马数字转整数)
  6. 优先级队列用的的数据结构
  7. Swift语言高速入门
  8. SpringBoot使用ControllerAdvice和ExceptionHandler进行统一异常处理
  9. django 1.8 官方文档翻译: 2-1-1 模型语法(初稿)
  10. LoadRunner - 实战,转发
  11. java中long的包装类_Java中基本数据的包装类
  12. DIY购车入门5步法则
  13. stm32f adc matlab 串口,基于Matlab和串口通信的ADC动态性能FFT测试法
  14. 基于springBoot的社区信息管理系统
  15. 用Python实现一个动物识别专家系统--人工智能
  16. 努比亚 Z17(Nubia NX563J) 解锁BootLoader 并刷入recovery
  17. 微型计算机 2018 12月下,桌面CPU天梯图2018年12月最新版 十二月台式电脑处理器排名...
  18. 【HTML】网页的基本结构
  19. 人工智能,你欠我们一个解释
  20. PHP环境安装步骤及详解

热门文章

  1. 3d数字孪生项目开发分享
  2. HTML中gt的含义
  3. 仿真软件proteus构建七段数码管显示数字0-9实验
  4. python 字典计数_python怎么用字典计数
  5. Apk脱壳圣战之—如何脱掉“梆梆加固”的保护壳
  6. 7个月时间“从零到亿”,社交电商靠谱好物为何总能占据行业“C位”?
  7. PowerDesigner 15及破解补丁_PowerDesigner 12.5及破解补丁_PowerDesigner破解版_PowerDesigner下载
  8. gamemaker 更新 runtime 快一点
  9. 第02章 c语言初探(c语言笔记)2.1 第一个 C 语言程序
  10. SpringBoot 项目实现 Excel 导入导出功能