一个整数使用英文表达的字母计数

2024-06-23 18:36

本文主要是介绍一个整数使用英文表达的字母计数,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

  • 题目:

把1到5写成英文单词分别是:one、two、three、four、five。这些单词一共用了3+3+5+4+4 = 19 个字母。

如果把1到1000都写成英文单词,一共要用多少个字母?

注:不计入空格和连字符,例如,342,three hundred and forty-two, 包含23哥字母,而115(one hundred and fifteen)包含20个字母。单词“and” 的使用方式遵循英式英语的规则。

  • 题目分析

通过题目描述,我们可以知道这是一个枚举问题,但是从1~1000逐个枚举,显然不是题目的目的,枚举也是有技巧的,有规律可循的,我们的任务就是找到其中的规律。

20twenty30thirty
1one11eleven21twenty-one31thirty-one
2two12twelve22twenty-two32thirty-two
3three13thirteen23twenty-three33thirty-three
4four14fourteen24twenty-four34thirty-four
5five15fifteen25twenty-five35thirty-five
6six16sixteen26twenty-six36thirty-six
7seven17seveteen27twenty-seven37thirty-seven
8eight18eighteen28twenty-eight38thirty-eight
9nine19nineteen29twenty-nine39thirty-nine
10ten

通过这个表格可以看到,1~19 的英文单词是没有规律的,但是21~29, 31~39 是有规律的,分别是20 + 1~9, 30+1~9,以此类推,41~49,51~59 ,直到91~99,都是对应的十位数加上个位数,这似乎就是一个规律了。

我们总结一下:

定义一个函数f(n), 求n用英文表示以后所需要的字母个数,则有如下情况:

1. 当n < 20 时, f(n) 可以通过查表求得;

2. f(21) = f(20) + f(1),  f(37)  =  f(30) + f(7), f(92) = f(90) + f(2);

3. 当n < 100 时, 通过下列结果的值,可求出此范围内其他结果的值:

f(1) , f(2), f(3), f(4), f(5), f(6), f(7), f(8), f(9), f(10), f(11), f(12), f(13), f(14), f(15), f(16), f(17), f(18), f(19), f(20), f(30), f(40), f(50), f(60), f(70), f(80), f(90);

4. 为了计算方便,规定f(0) = 0;

5. 当任意给定一个数字n , 20 <= n <= 100 , 

获得十位上的数:m = n /10 ;获得 个位上的数: l = n % 10;

所以: f(n) = f( m* 10) + f(l)。

6. 当n >= 100 时, 

获得百位上的数:h = n / 100 ;

获得十位 和 个位 上的数:m = n  % 100 

f(n) = f(h) + 8(hundred) +  3(and) + f(m); 

Tip:卖个关子,这里为什么将十位和个位上的数字需要整体处理? 谜底见代码实现部分。

分析到这里,我们来想想需要多少个数据结构来存储固定数据值:

arr1 用于存放0~19:  int arr1[20] = {} 

arr2 用于存放整十 数值(20,30,30,40,50,60,70,80,90): int arr2[9] = {} 

data1 用于表示"and";

data2 用于表示“hundred”

data3 用于表示 “one thousand”

  • 代码实现:
#include <stdio.h>#define HUNDRED 7#define ONE_THOUSAND 11#define AND 3int get_letters(int n){static int arr1[20] = {0, 3,3,5,4,4,3,5,5,4,3,6,6,8,8,7,7,9,8,8};static int arr2[10] = {0,0,6,6,5,5,5,7,6,6};if(n < 20) return arr1[n];if(n < 100){return arr2[n/10] + arr1[n%10];}if(n < 1000){if(n % 100 == 0) return arr1[n/100]+ HUNDRED;return arr1[n/100]+HUNDRED + AND +  get_letters(n%100);}return ONE_THOUSAND;}int main(){int sum = 0;for(int i = 1; i <= 1000;i++){sum += get_letters(i);}printf("sum = %d\n",sum);return 0;}
  • 运行结果:

  • 分析总结:

1. 这道题目比较简单,但是训练了我们的计算机思维以及规律总结能力;

2. 思考3个问题:

1) 为什么函数get_letters 中的arr1 和arr2 要定义为static?

2) 函数get_letters中的arr1[0], arr2[0], arr[1] 为什么要初始化为0?

3)在函数get_letters中递归调用get_letters 有什么好处?

答:

1)对于第一个问题,我们可以换一个问法,“为什么这段代码中将局部变量声明称为静态?”,

首先,这是因为变量声明为静态它的初始化就只会进行一次,虽然多次调用了这个函数,但是对这个变量的初始化就只会在第一次调用时发生,因此,减少了内存分配和回收的开销,从而提高了程序的性能;

第二,声明为静态,这个局部变量的存储位置就由栈变为静态存储区,栈的空间是有限的,这样做节省了栈空间,

第三,声明为静态,虽然它的生命周期延长了,但是由于是局部变量,所以它的作用域还是受到限制的,仅限在这个函数内部, 所以避免了污染全局命名空间

2) arr1[0] = 0 , 这是因为arr1[0] 表示的是变量0, 但是我们操作的数据规模是1~1000, 这个值没有用到;

      arr2[0]  表示一个数字的十位上0, arr2[1], 表示一个数字的十位上1, 但是经过分析英文单词的特点,已经将10~19 初始化到arr1 中,所以如果当前数字的十位上是0 或1 ,我们就去arr1去找对应的值,arr2 就从arr[2] 开始设置初始值。

3) 关于get_letters函数的递归调用,发生在处理当前数值是三位数的情况,并且是用于处理除去百位数后剩下的2位数, 因为剩下的两位数,又可以分为两种情况,即0~20 和20~99, 所以此时用递归调用,将待处理数据直接传入函数,减少了代码分析的难度,使逻辑分析更清楚,也避免了代码出错的概率。

这篇关于一个整数使用英文表达的字母计数的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1087945

相关文章

Android kotlin中 Channel 和 Flow 的区别和选择使用场景分析

《Androidkotlin中Channel和Flow的区别和选择使用场景分析》Kotlin协程中,Flow是冷数据流,按需触发,适合响应式数据处理;Channel是热数据流,持续发送,支持... 目录一、基本概念界定FlowChannel二、核心特性对比数据生产触发条件生产与消费的关系背压处理机制生命周期

java使用protobuf-maven-plugin的插件编译proto文件详解

《java使用protobuf-maven-plugin的插件编译proto文件详解》:本文主要介绍java使用protobuf-maven-plugin的插件编译proto文件,具有很好的参考价... 目录protobuf文件作为数据传输和存储的协议主要介绍在Java使用maven编译proto文件的插件

SpringBoot线程池配置使用示例详解

《SpringBoot线程池配置使用示例详解》SpringBoot集成@Async注解,支持线程池参数配置(核心数、队列容量、拒绝策略等)及生命周期管理,结合监控与任务装饰器,提升异步处理效率与系统... 目录一、核心特性二、添加依赖三、参数详解四、配置线程池五、应用实践代码说明拒绝策略(Rejected

C++ Log4cpp跨平台日志库的使用小结

《C++Log4cpp跨平台日志库的使用小结》Log4cpp是c++类库,本文详细介绍了C++日志库log4cpp的使用方法,及设置日志输出格式和优先级,具有一定的参考价值,感兴趣的可以了解一下... 目录一、介绍1. log4cpp的日志方式2.设置日志输出的格式3. 设置日志的输出优先级二、Window

Ubuntu如何分配​​未使用的空间

《Ubuntu如何分配​​未使用的空间》Ubuntu磁盘空间不足,实际未分配空间8.2G因LVM卷组名称格式差异(双破折号误写)导致无法扩展,确认正确卷组名后,使用lvextend和resize2fs... 目录1:原因2:操作3:报错5:解决问题:确认卷组名称​6:再次操作7:验证扩展是否成功8:问题已解

Qt使用QSqlDatabase连接MySQL实现增删改查功能

《Qt使用QSqlDatabase连接MySQL实现增删改查功能》这篇文章主要为大家详细介绍了Qt如何使用QSqlDatabase连接MySQL实现增删改查功能,文中的示例代码讲解详细,感兴趣的小伙伴... 目录一、创建数据表二、连接mysql数据库三、封装成一个完整的轻量级 ORM 风格类3.1 表结构

使用Docker构建Python Flask程序的详细教程

《使用Docker构建PythonFlask程序的详细教程》在当今的软件开发领域,容器化技术正变得越来越流行,而Docker无疑是其中的佼佼者,本文我们就来聊聊如何使用Docker构建一个简单的Py... 目录引言一、准备工作二、创建 Flask 应用程序三、创建 dockerfile四、构建 Docker

Python使用vllm处理多模态数据的预处理技巧

《Python使用vllm处理多模态数据的预处理技巧》本文深入探讨了在Python环境下使用vLLM处理多模态数据的预处理技巧,我们将从基础概念出发,详细讲解文本、图像、音频等多模态数据的预处理方法,... 目录1. 背景介绍1.1 目的和范围1.2 预期读者1.3 文档结构概述1.4 术语表1.4.1 核

Python使用pip工具实现包自动更新的多种方法

《Python使用pip工具实现包自动更新的多种方法》本文深入探讨了使用Python的pip工具实现包自动更新的各种方法和技术,我们将从基础概念开始,逐步介绍手动更新方法、自动化脚本编写、结合CI/C... 目录1. 背景介绍1.1 目的和范围1.2 预期读者1.3 文档结构概述1.4 术语表1.4.1 核

Conda与Python venv虚拟环境的区别与使用方法详解

《Conda与Pythonvenv虚拟环境的区别与使用方法详解》随着Python社区的成长,虚拟环境的概念和技术也在不断发展,:本文主要介绍Conda与Pythonvenv虚拟环境的区别与使用... 目录前言一、Conda 与 python venv 的核心区别1. Conda 的特点2. Python v