共计 3178 个字符,预计需要花费 8 分钟才能阅读完成。
题目粗心:
依照中文发音规定输入一个绝对值在 9 位以内的整数。
算法思路:
此题考查的细节次要在 0 和 Wan 的输入上,因为只有 9 位,那么最高位只会达到亿。那么首先应用 units
数组寄存每一位数字的单位 (从个、十、百到亿),因为万,十万,百万,千万的单位每一个都有万字,然而在输入的时候只有该组数位中不为 0 数字对应的最小单位才会带上万输入,所以,这里在units[4]
存储 Wan, 其余位只存储十,百,千。同时应用 nums
数组存储所有的数字对应的中文拼音,下标 (int
) 和数字 (string
) 为一一对应关系。因为这里因为万位数字的非凡解决关系,将数字分为三个局部:
1、个、十、百、千,也就是从右往左第一个到第四个数字
2、万、十万、百万、千万,也就是从右往左第五个到第八个数字
3、亿,也就是从右往左第九个数字
那么咱们首先将数字 N 转存到数组 digits
中,其程序恰好是逆序,这样咱们从左往右依照每一个局部进行解决。对于万位数字的解决,咱们应用 is_first_wan
变量记录以后的万位数字是否是呈现的第一个万位数字,如果是,那么得增加 Wan。这里为了更加不便的解决 0 的输入,得先进行预处理,首先咱们留神到,只有 2 个不为 0 的数字间隔相差大于 1 的不论两头有几个 0 存在,最初都只会输入一个 0,所以,咱们应用数组 non_zero
和non_zero_index
别离保留 digits
数组中不为 0 的数字以及其在 digits
中的下标地位, 这里不采纳 hash
的办法来记录地位和对应的值是因为不同数位上的数字会呈现反复。接着就是遍历 non_zero
数组,
解决所有的不为 0 的数字,应用 vector<string> result
保留最初的后果
个、十、百、千位的解决:
1、如果不是第一位不为 0 的数字,并且与上一位数字的地位相差大于 1,咱们首先增加 0(result.push_back(nums[0])
)
2、如果以后位是个位,只增加对应的数字result.push_back(nums[non_zero[j]])
,如果不是,得先增加单位result.push_back(units[non_zero_index[j]])
万、十万、百万、千万位的解决:
1、如果不是第一位不为 0 的数字,并且与上一位数字的地位相差大于 1,咱们首先增加 0(result.push_back(nums[0])
)
2、如果是第一次呈现万位数字,首先得增加一个 Wan, 而后让 is_first_wan
为false
;
3、如果以后位数字恰好为第五个(也就是万),那么肯定是第一次呈现的,所以只须要增加数字即可,否则就得增加上十,百,千补全单位,而后再增加数字
亿位的解决:
1、如果不是第一位不为 0 的数字,并且与上一位数字的地位相差大于 1,咱们首先增加 0(result.push_back(nums[0])
)
2、先增加单位,而后增加数字。
从下面能够看到因为都须要解决 0, 于是能够将该步骤抽取进去作为公共代码局部。
符号的解决:对于正数,在最初增加一个 Fu 即可
result 的输入:逆序输入,对于 i >0 的状况,得输入空格。
留神点:
1、如果在个位增加了单位,也就是字符串数组中增加了 ””, 会输入多与的空格,测试点 0 和测试点 4 就会呈现格局谬误
2、边界数据 0,该当间接输入 ling,测试点 3 考查
3、测试点 1 谬误的能够思考如下数据:808808808,ba Shi Wan 前面不须要再输入 ling, 而是间接输入 ba Qian
给出一组测试数据:
808080808 ba Yi ling ba Bai ling ba Wan ling ba Bai ling ba
-880808080 Fu ba Yi ba Qian ling ba Shi Wan ling ba Qian ling ba Shi
800000008 ba Yi ling ba
800000000 ba Yi
80000008 ba Qian Wan ling ba
80008000 ba Qian Wan ling ba Qian
80000000 ba Qian Wan
提交后果:
AC 代码:
#include <cstdio>
#include <string>
#include <vector>
using namespace std;
int main()
{string units[9] = {"","Shi","Bai","Qian","Wan","Shi","Bai","Qian","Yi"};
string nums[10] = {"ling","yi","er","san","si","wu","liu","qi","ba","jiu"};
int N;
int digits[10];
int index = 0;//digit 的工作指针
scanf("%d",&N);
int n = N;
if(n<0){n = -n;}
if(n==0) {
// 0 特判
printf("ling");
return 0;
}
// 将 n 的每一位应用 digits 数组存储
while (n!=0){digits[index++] = n%10;
n /= 10;
}
// 从左到右遍历 digits 数组(也即是从后往前遍历数字的每一位),记录所有不为 0 的数字及其地位
int non_zero[10];// 保留所有不为 0 的数字
int non_zero_index[10];// 保留所有不为 0 数字对应的下标
int non_zero_p = 0;//non_zero 的工作指针
for (int i = 0; i < index; ++i) {if(digits[i]!=0){non_zero[non_zero_p] = digits[i];
non_zero_index[non_zero_p] = i;
++non_zero_p;
}
}
// 遍历 non_zero 数组,解决所有的不为 0 的数字
vector<string> result;// 保留后果汇合
bool is_first_wan = true;// 判断是否曾经增加了 Wan
for (int j = 0; j < non_zero_p; ++j) {
// 首选解决数字 0
if(j!=0&&(non_zero_index[j]-non_zero_index[j-1])>1){
// 不是个位数字,并且与上一位数字的地位相差大于 1
result.push_back(nums[0]);// 增加一个 0
}
if(non_zero_index[j]<4){
// 个、十、百、千位
if(non_zero_index[j]!=0){// 个位的单位不能增加,因为 "" 也会输入一个空格, 测试点 0 和 4 考查
result.push_back(units[non_zero_index[j]]);
}
result.push_back(nums[non_zero[j]]);
} else if(non_zero_index[j]<8) {
// 万、十万、百万、千万位
if(is_first_wan){
// 第一次呈现万位及其以上的状况
result.push_back(units[4]);// 增加一个 Wan
is_first_wan = false;
}
if(non_zero_index[j]!=4){
// 十万、百万、千万位须要在万后面增加十、百、千
result.push_back(units[non_zero_index[j]]);
}
// 最初增加数字
result.push_back(nums[non_zero[j]]);
} else {
// 亿位
result.push_back(units[non_zero_index[j]]);
result.push_back(nums[non_zero[j]]);
}
}
if(N<0) {result.emplace_back("Fu");
}
for (int i=result.size()-1;i>=0;--i) {printf("%s",result[i].c_str());
if(i>0) printf(" ");
}
return 0;
}