将非负整数num转换为对应的英文表达(C++实现)—— 力扣第273号题的加强。

news2024/12/24 22:11:10

【问题描述】

将非负整数num转换为对应的英文表达式。

(样例1)

输入:25

输出:Twenty Five

(样例2)

输入:12,315

输出:Twelve Thousand Three Hundred (and) Fifteen 

备注:and可省略

另备注:偶然发现这个算法问题,并进行了尝试,当时并不知道是力扣原题(Q273,官网给出的num其范围为0~2^31 - 1),故从严谨性和通用性考虑,假定了num为64位无符号整数。

【思考过程】

        按数学定义,num为非负整数集合(包含0),虽然题设没有给出整数num的取值上限,但考虑到题解的通用性可将num的取值上限定为2^63 - 1。另外,还需要了解数字对应的英文如何表达(特别是一些较大的数字),为此可参照下面的表格总结出表达规律:

Number

In English Phrase

Notes

0

Zero

25

Twenty Five

127

One Hundred (and) Twenty Seven

(and)可省略

1,024

One Thousand (and) Twenty Four

(and)可省略

12,315

Twelve Thousand Three Hundred (and) Fifteen

(and)可省略

589,001

Five Hundred (and) Eighty Nine Thousand (and) One

16,000,014

Sixteen Million (and) Fourteen

1,000,000,000

One Billion

9,223,372,036,854,775,807 = (2^63 -  1)

Nine Quintillion ,

Two Hundred Twenty Three Quadrillion ,

Three Hundred Seventy Two Trillion ,

Thirty Six Billion ,

Eight Hundred Fifty Four Million ,

Seven Hundred Seventy Five Thousand ,

Eight Hundred Seven

Quintillion:1018 

Quadrillion:1015

Trillion:1012

Billion:109

Million:106

Thousand: 103

        很容易观察到,表达时从最低数位开始(按每三位一组进行划分,不足三位就取实际位数)依次表达到最高数位为止,具体理解如下:

        每三位一组(不够三位的取实际位数),记a,b,c分别为百位、十位、个位上对应的数字,三者组合起来可以得到实际数值为0~999的任意整数,故我们只需要将该实际数值表达为英语即可,同时还需要加上数量级的表达(如thousand,million之类的)。 

        现在可以来考虑实际编码工作:对于0~19,20、30、40、...、90这些数字,对应的英文表达可提前用字符串数组存放起来,并将这部分的数字解析工作交由to_single_digit()与to_double_digit()两函数来完成(这两个函数共同处理num < 100的数字);对于100及以上的数字,按每三位一组进行表达,同时还需要加上当前数量级的表达(数量级的英语表达可用哈希表unordered_map容器存放起来,以便编程时的直接引用),具体而言,这部分的数字解析工作交由to_complex_digit()函数来完成。

        在to_complex_digit()函数中,应循环地去处理每个数字分组,将其翻译表达为对应的英文。因为我们是从低位数字分组一直处理到高位数字分组,故需要同时用到队列和栈这两种数据结构。其中,队列中存放的是某个数字分组对应的英文表达(且队列中不会同时存放多个数字分组对应的英文表达),而栈中会依次压入之前处理好的每组英文表达(以便最后陆续出栈时,拼接为最终整体的英文表达结果)。

[代码实现]

#include<iostream>
#include<string>
#include<queue>
#include<stack>
#include<unordered_map>
#include<cmath>

using namespace std;
using ull = unsigned long long;

class NumToEnglish
{
private:
	string ans;
	
	string table_0_19[20] = {"Zero", "One", "Two", "Three", 
		"Four", "Five", "Six", "Seven", 
		"Eight", "Nine", "Ten", "Eleven",
		"Twelve", "Thirteen", "Fourteen", "Fifteen",
		"Sixteen", "Seventeen", "Eighteen", "Nineteen"};
	
	string table_20_90[8] = {"Twenty", "Thirty", "Forty", "Fifty",
		"Sixty", "Seventy", "Eighty", "Ninety"};
	
	unordered_map<ull, string> table_sepcial = {
		{1e3, "Thousand"}, {1e6, "Million"},
		{1e9, "Billion"}, {1e12, "Trillion"}, {1e15, "Quadrillion"},
		{1e18, "Quintillion"}
	};
	
	//将队列中的内容转换为一个字符串
	string queue_to_string(queue<string>& Q)
	{
		string res;
		
		while(!Q.empty())
		{
			res.append(Q.front());
			Q.pop();
		}
		
		return res;
	}
	
	//将栈中的内容转换为一个字符串
	string stack_to_string(stack<string>& S)
	{
		string res;
		
		while(!S.empty())
		{
			res.append(S.top());
			S.pop();
		}
		
		return res;
	}
	
	string to_single_digit(int num)  //0~19
	{
		return table_0_19[num];
	}
	
	string to_double_digit(int num) //20~99
	{
		string res;
		
		if(num < 20)
		{
			res = to_single_digit(num);
		}
		else
		{
			int sw = num / 10;
			int gw = num % 10;
			
			res.append(table_20_90[sw - 2]);
			if(gw != 0)
			{
				res.append(" ");
				res.append(table_0_19[gw]);
			}
		}
		
		return res;
	}
	
	string to_complex_digit(ull num) //100~2^63 - 1
	{
		queue<string> qu;
		stack<string> st;
		string tmp = to_string(num);  //转换为string, 每三位一组解析数据
		string res;
		
		//i: 指向每组数据的开头, pre_start: 指向上一组数据的开头
		int len = tmp.size();
		int i = len - 3, pre_start = len, bw, sw, gw;
		ull factor = 1;  //数量级标识: thousand, million... etc
		
		while(i >= 0)
		{
			int sublen = pre_start - i;  //每组数据的长度
			bool zero_flag = false;     //每组数据是否全为0的标志
			
			//根据每组数据的长度, 来计算出英文表达
			if(sublen == 3)
			{
				bw = tmp[i] - '0';
				sw = tmp[i + 1] - '0';
				gw = tmp[i + 2] - '0';
				
				sw = sw * 10 + gw;  //将每组的个位和十位合并后再处理
				
				if(bw != 0) 
				{
					qu.emplace(to_single_digit(bw)), qu.emplace(" ");
					qu.emplace("Hundred");
					if(sw != 0)
					{
						qu.emplace(" "), qu.emplace(to_double_digit(sw));
					}
				}
				else
				{
					if(sw != 0) qu.emplace(to_double_digit(sw));
				}
				
				zero_flag = !(gw || sw || bw);
			}
			else if(sublen == 2)
			{
				sw = tmp[i] - '0';
				gw = tmp[i + 1] - '0';
				
				sw = sw * 10 + gw;  //将每组的百位和十位合并后再处理
				if(sw != 0)         qu.emplace(to_double_digit(sw));
				
				zero_flag = !(gw || sw);
			}
			else  //sublen == 1
			{
				gw = tmp[i] - '0';
				qu.emplace(table_0_19[gw]);
				
				zero_flag = !gw;
			}
			
			//加上当前数量级的英文表达
			if(factor != 1 && zero_flag != true) 
			{
				qu.emplace(" " + table_sepcial[factor]);  
			} 
			
			if(!qu.empty()) st.emplace(queue_to_string(qu) + " "); //将当前这组处理数据压入栈中
			
			//若还有剩余的高位组数据, 则更新i, pre_start, factor的取值
			if(i == 0) break;
			
			factor *= 1e3;   //扩大数量级, 以便处理下一组数据
			pre_start = i;
			if(i - 3 >= 0) i -= 3;
			else if(i - 2 >= 0) i -= 2;
			else if(i - 1 >= 0) --i;
		}
		
		res = stack_to_string(st);
		
		return res;
	}
	
public:
	string transform(ull num)  //用户接口(将数字转为英文表达)
	{
		if(num < 100)
		{
			ans = to_double_digit(num);
		}
		else
		{
			ans = to_complex_digit(num);
		}
		
		return ans;
	}
};

int main()
{
	ull num;
	cin >> num;
	
	NumToEnglish nte;
	cout << nte.transform(num) << endl;
	
	return 0;
}

[测试结果]

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/144476.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

(八)devops持续集成开发——jenkins流水线发布一个docker版的后端maven项目

前言 本节内容我们使用jenkins的流水化工具发布一个后端docker项目&#xff0c;实现后端项目的容器化部署。在开始本节内容之前&#xff0c;我们需要在生产环境安装好docker环境并且能够联网下载镜像。通过jenkins的流水化工具&#xff0c;实现代码拉取&#xff0c;maven打包编…

【java篇】反射机制简单理解

学到JDBC后&#xff0c;使用到反射机制&#xff0c;所以回顾反射机制相关知识点&#xff1b; 文章目录 文章目录 什么是反射机制&#xff1f; 如何理解反射呢&#xff1f; 总结 一、Java反射机制是什么&#xff1f; 二、Java反射机制中获取Class的三种方式及区别&#xff1f; 三…

【目标检测】EfficientDet

1、论文 题目&#xff1a;《EfficientDet: Scalable and Efficient Object Detection》 论文地址&#xff1a; https://arxiv.org/pdf/1911.09070.pdf 代码地址&#xff1a; https://github.com/bubbliiiing/efficientdet-pytorch 2、摘要 Google Brain团队在CVPR 2020上提出…

Liunx 对函数库的理解

一、前言 我们的C程序中&#xff0c;并没有定义“printf”的函数实现,且在预编译中包含的“stdio.h”中也只有该函数的声明,而没有定义函数的实现,那么,是在哪里实“printf”函数的呢?最后的答案是:系统把这些函数实现都被做到名为 libc.so.6 的库文件中去了,在没有特别指定时…

PCB入门学习— CHIP类PCB封装的创建

目录 2.12 原理图PCB封装完整性的检查 3.1 CHIP类PCB封装的创建 学习目录 2.12 原理图PCB封装完整性的检查 然后点接受变更。 www.digikey.com搜索规格的网站。 3.1 CHIP类PCB封装的创建 放焊盘——确定大小——画丝印——确定原点EFC。 创建一个PCB元件库&#xff0c;Ct…

React(coderwhy)- 07(路由)

认识React-Router 认识前端路由 ◼ 路由其实是网络工程中的一个术语&#xff1a;  在架构一个网络时&#xff0c;非常重要的两个设备就是路由器和交换机。  当然&#xff0c;目前在我们生活中路由器也是越来越被大家所熟知&#xff0c;因为我们生活中都会用到路由器&#x…

红黑树:比AVL抽象、自由的、更广泛的近似平衡树

RBT与AVL树的比较 AVL&#xff1a;高度要求差不超过1红黑树&#xff1a;RBT要求最长路径不超过短路径的2倍&#xff0c;不需要像AVL一样太平衡&#xff0c;稍微自由&#xff0c;所以旋转较少。 AVL和RBT树性能比较&#xff1a; 插入同样的数据&#xff0c;AVL树旋转更多&…

本地生活配送行业黑马,带你一键读懂闪飞侠

电商的黄金十年已经过去&#xff0c;本地生活的黄金市场才刚刚开启&#xff0c;本地生活市场的增长对同城配送的影响得有多大&#xff1f;2020年的新冠疫情&#xff0c;爆发了同城即时配送的投资新机遇&#xff01;即时配送用户已超5亿。而随着即时配送行业的广泛应用&#xff…

【 Vue3 + Vite + setup语法糖 + Pinia + VueRouter + Element Plus 第三篇】(持续更新中)

在第二篇我们主要学习了路径别名&#xff0c;配置.env环境变量&#xff0c;封装axios请求&#xff0c;以及使用api获取数据后渲染 Element Plus表格 本期需要掌握的知识如下: 封装列表模糊查询组件实现新增 编辑 删除 模糊查询 重置 功能实现表单校验功能实现组件间传值 下期…

Compose跨平台第一弹:体验Compose for Desktop

前言 Compose是Android官方提供的声明式UI开发框架&#xff0c;而Compose Multiplatform是由JetBrains 维护的&#xff0c;对于Android开发来说&#xff0c;个人认为学习Jetpack Compose是必须的&#xff0c;因为它会成为Android主流的开发模式&#xff0c;而compose-jb作为一…

TikTok三大流行趋势 钛动带你看懂TikTok

武汉瑞卡迪电子商务有限公司&#xff1a;近日,TikTok for Business发布了《Whats Next 2023 TikTok 全球流行趋势报告》,就2023年TikTok三大趋势主题进行了介绍。 钛动科技作为TikTok官方授权代理商,是TikTok生态服务最齐全的出海服务商,凭借出色的技术与服务能力,钛动斩获了T…

论 G1 收集器的架构和如何做到回收时间用户设定

目录G1 概念JVM的内存分代假设让用户设置应用的暂停时间G1 概念 G1其实是Garbage First的意思&#xff0c;它不是垃圾优先的意思&#xff0c;而是优先处理那些垃圾多的内存块的意思。 在大的理念上&#xff0c;它还是遵循JVM的内存分代假设。 JVM的内存分代假设 JVM的内存分代…

https如何加密解密?

背景 我们知道&#xff0c;https&#xff0c;在网络传输中&#xff0c;加密。具体来说是数据加密。//客户端和服务器&#xff0c;写数据的时候&#xff0c;都会加密。即1.客户端——》服务器 2.服务器——》客户端。 如何加密 解密&#xff1f; 加密解密 想要加密和解密&am…

【Mysql篇】数据库事务

目录 数据库事务数据库事务介绍 JDBC事务处理 事务的ACID属性 数据库的并发问题 数据库提供的4种事务隔离级别&#xff1a; 在MySql中设置隔离级别 数据库事务数据库事务介绍 事务&#xff1a;一组逻辑操作单元,使数据从一种状态变换到另一种状态。 事务处理&#xff08;…

Day1. Spring

1 课程描述IoC基础容器&#xff0c;主要涉及Bean对象的管理。AOP面向切面编程&#xff0c;主要涉及切面配置&#xff0c;声明式事务控制Spring整合Web环境。Web层解决方案-SpringMVC.1.1 IoC、DI和AOP思想的提出由于传统的JavaWeb出现的问题&#xff1a;问题1&#xff1a;层与层…

【问题记录】Process finished with exit code -1073740791 (0xC0000409) 注:LSTM股票预测案例中

目录 1. 问题来源2. 问题解决1. 问题来源 在跑一段 LSTM&神经网络 股票预测的代码时,遇到了下述报错,报错提示为: Process finished with exit code -1073740791 (0xC0000409) 报错截图为: 下面是整个报错的内容,这里我也截取下来了: H:\Python学习专用\深度学习\LS…

ECMAScript基础入门

JavaScript&#xff08;浏览器端&#xff09;ECMAScript&#xff08;语法API&#xff09;DOMBOM es6开始let代替var声明变量&#xff08;初始化后可重新赋值&#xff09;&#xff0c;而const声明常量&#xff08;初始化后不可重新赋值&#xff0c;否则会报错&#xff09; con…

Java调用百度OCR接口实现文字识别

博主在项目开发中需要完成一个文字识别功能&#xff0c;由于之前有过使用百度云平台接口进行身份证识别的经历&#xff0c;因此这次也是自然而然的再次选择了百度AI平台&#xff0c;首先需要开通百度通用文字识别功能。 然后我们需要创建一个应用&#xff1a; 然后我们就可以…

TensorFlow 基础(一)张量

文章目录BasicsAbout shapesIndexingSingle-axis indexingMulti-axis indexingManipulating ShapesMore on dtypesReferencesimport tensorflow as tf import numpy as npBasics 张量是具有统一类型&#xff08;dtype&#xff09;的多维数组。它和 NumPy 中的 np.arrays 是非常…

C进阶_C语言_函数与指针_C语言指针进阶

上一篇博客http://t.csdn.cn/GYCiM 我们了解了指针相关知识&#xff0c;今天来了解函数和指针的关系。 目录 函数指针 函数指针数组 指向函数指针数组的指针 回调函数 qsort 冒泡排序模拟实现qsort 函数指针 我们知道&#xff0c;数组指针是指向数组的指针。 int arr[…