题解 | #人民币转换#

人民币转换

http://www.nowcoder.com/practice/00ffd656b9604d1998e966d555005a4b

题意

题目直接就是题意

1、中文大写金额数字前应标明“人民币”字样。中文大写金额数字应用壹、贰、叁、肆、伍、陆、柒、捌、玖、拾、佰、仟、万、亿、元、角、分、零、整等字样填写。

2、中文大写金额数字到“元”为止的,在“元”之后,应写“整字,如532.00应写成“人民币伍佰叁拾贰元整”。在”角“和”分“后面不写”整字。

3、阿拉伯数字中间有“0”时,中文大写要写“零”字,阿拉伯数字中间连续有几个“0”时,中文大写金额中间只写一个“零”字,如6007.14,应写成“人民币陆仟零柒元壹角肆分“。

4、10应写作“拾”,100应写作“壹佰”。例如,1010.00应写作“人民币壹仟零拾元整”,110.00应写作“人民币壹佰拾元整”

5、十万以上的数字接千不用加“零”,例如,30105000.00应写作“人民币叁仟零拾万伍仟元整”

方法

实现

先拆解类别

1~9: 壹、贰、叁、肆、伍、陆、柒、捌、玖

10/100/100/10000/100000000: 拾、佰、仟、万、亿

小数:角、分

单位:元

特殊:零、整


把文字变为逻辑

整:当角和分都是零的时候出现

零:4个一组,连续的合并,且和末尾不连接

万:万的4个数字非全0

拾:单位是1时不输出1

把上述逻辑转换成代码


以样例数据151121.15为例

操作 字符 剩余处理部分
初始化 - 151121.15
处理'整'/'角'/'分' 壹角伍分 151121
处理后4位 - 1121
处理1 1121
处理2 贰拾壹 1121
处理1 壹佰贰拾壹 1121
处理1 壹仟壹佰贰拾壹 1121
拼接到结果 壹仟壹佰贰拾壹元壹角伍分 15
处理高4位 - 15
处理5 15
处理1 拾伍 15
拼接到结果 拾伍万壹仟壹佰贰拾壹元壹角伍分 -

代码

#include<bits/stdc++.h>
using namespace std;

string ch[] = {
    "零",
    "壹",
    "贰",
    "叁",
    "肆",
    "伍",
    "陆",
    "柒",
    "捌",
    "玖"
};

string chstr(string s){
    string str = "";
    int n = s.length();
    if(s[n-1] != '0'){ // 全为零不输出
        str += ch[s[n-1]-'0'];
    }
    if(n-2 >= 0){
        if( s[n-2] != '0'){
            if(s[n-2] != '1'){
                str = ch[s[n-2]-'0'] + "拾" + str;
            }else{
                str = "拾" + str;
            }
        }else if(str.length() != 0 && str.rfind("零",0) != 0){ // 不要连续零
            str = "零" + str;
        }
    }
    
    if(n-3 >= 0){
        if(s[n-3] != '0'){
            str = ch[s[n-3]-'0'] + "佰" + str;
        }else if(str.length() != 0 && str.rfind("零",0) != 0){  // 不要连续零
            str = "零" + str;
        }
    }
    
    if(n-4 >= 0){
        if(s[n-4] != '0'){
            str = ch[s[n-4]-'0'] + "仟" + str;
        }else if(str.length() != 0 && str.rfind("零",0) != 0){ // 不要连续零
            str = "零" + str;
        }
    }
    return str;
}

int main(){
    char s[20];
    while(~scanf("%s",s)){
        int n = strlen(s);
        // 是否 整数 和 角 分
        bool zheng = s[n-1] == '0' && s[n-2] == '0';
        string res = zheng ? "整" : "";
        if(s[n-1] != '0'){
            res = ch[s[n-1]-'0'] + "分" + res;
        }
        if(s[n-2] != '0'){
            res = ch[s[n-2]-'0'] + "角" + res;
        }
        // 整数部分
        string ywy[] = {"元","万","亿"}; // 四个一组的单位
        int itr = 0;
        for(int i = n - 4;i >= 0;i-=4){
            string s4 = ""; // 4个数一组
            for(int j = 0;j < 4 && i-j>=0;j++){
                s4 = s[i-j] + s4;
            }
            string cs = chstr(s4); // 转换成 字符
            if(cs.length() > 0){ // 为空不输出单位
                res = cs + ywy[itr++] + res;
            }
        }
        cout<<"人民币"<<res<<endl;
    }
    return 0;
}

复杂度分析

时间复杂度: 对于每一个位置,相关操作次数为常数次,所以总时间复杂度为O(n)O(n)

空间复杂度: 主要空间消耗在读入和生成的字符串,所以空间复杂度为O(n)O(n)

输出时合并零

对于上面的过程,还可以简化处理中的零处理,在过程中,只关心是不是4个连续中的末尾0链接。对于中间的零,均记为零

最后输出时再忽略掉连续的零。

因为string中的中文十分难取,所以这里改用 deque 来记录字符串,方便比较相邻的中文。

代码

#include<bits/stdc++.h>
using namespace std;

string ch[] = {
    "零",
    "壹",
    "贰",
    "叁",
    "肆",
    "伍",
    "陆",
    "柒",
    "捌",
    "玖"
};

deque<string> chstr(string s){
    deque<string> res;
    int n = s.length();
    if(s[n-1] != '0'){
        res.push_front(ch[s[n-1]-'0']);
    }
    if(n-2 >= 0){
        if( s[n-2] != '0'){
            res.push_front("拾");
            if(s[n-2] != '1'){
                res.push_front(ch[s[n-2]-'0']);
            }
        }else if(res.size()){ // 只考虑 是否和末尾的零连续
            res.push_front("零");
        }
    }
    
    if(n-3 >= 0){
        if(s[n-3] != '0'){
            res.push_front("佰");
            res.push_front(ch[s[n-3]-'0']);
        }else if(res.size()){ // 只考虑 是否和末尾的零连续
            res.push_front("零");
        }
    }
    
    if(n-4 >= 0){
        if(s[n-4] != '0'){
            res.push_front("仟");
            res.push_front(ch[s[n-4]-'0']);
        }else if(res.size()){ // 只考虑 是否和末尾的零连续
            res.push_front("零");
        }
    }
    return res;
}

int main(){
    char s[20];
    while(~scanf("%s",s)){
        int n = strlen(s);
        // 是否 整数 和 角 分
        deque<string> res;
        if(s[n-1] == '0' && s[n-2] == '0'){
            res.push_back("整");
        }
        if(s[n-1] != '0'){
            res.push_front("分");
            res.push_front(ch[s[n-1]-'0']);
        }
        if(s[n-2] != '0'){
            res.push_front("角");
            res.push_front(ch[s[n-2]-'0']);
        }
        // 整数部分
        string ywy[] = {"元","万","亿"};
        int itr = 0;
        for(int i = n - 4;i >= 0;i-=4){
            string s4 = ""; // 4个数一组
            for(int j = 0;j < 4 && i-j>=0;j++){
                s4 = s[i-j] + s4;
            }
            auto cs = chstr(s4);
            if(cs.size() > 0){
                res.push_front(ywy[itr++]);
                for(int i = cs.size()-1;i>=0;i--){
                    res.push_front(cs[i]);
                };
            }
        }
        cout<<"人民币";
        for(int i = 0;i<res.size();i++){
            if(i > 1 && res[i] == res[i-1] && res[i] == "零"){ // 去掉连续的零
                continue;
            }
            cout<<res[i];
        }
        cout<<endl;
    }
    return 0;
}

复杂度分析

时间复杂度: 对于每一个位置,相关操作次数为常数次,所以总时间复杂度为O(n)O(n)

空间复杂度: 主要空间消耗在读入和生成的字符串,所以空间复杂度为O(n)O(n)

全部评论

相关推荐

拒绝无效加班的小师弟很中意你:求职意向没有,年龄、课程冗余信息可以删掉,需要提升项目经历。排版需要修改。
点赞 评论 收藏
分享
ProMonkey2024:5个oc?厉害! 但是有一个小问题:谁问你了?😡我的意思是,谁在意?我告诉你,根本没人问你,在我们之中0人问了你,我把所有问你的人都请来 party 了,到场人数是0个人,誰问你了?WHO ASKED?谁问汝矣?誰があなたに聞きましたか?누가 물어봤어?我爬上了珠穆朗玛峰也没找到谁问你了,我刚刚潜入了世界上最大的射电望远镜也没开到那个问你的人的盒,在找到谁问你之前我连癌症的解药都发明了出来,我开了最大距离渲染也没找到谁问你了我活在这个被辐射蹂躏了多年的破碎世界的坟墓里目睹全球核战争把人类文明毁灭也没见到谁问你了(别的帖子偷来的,现学现卖😋)
点赞 评论 收藏
分享
评论
点赞
收藏
分享
牛客网
牛客企业服务