zoukankan      html  css  js  c++  java
  • OJ练习47——T12 Integer to Roman

    把整数转换成罗马数字。数字不超过3999.

    罗马数字规律:1-I,5-V,10-X,50-L,100-C,500-D,1000M

    【对比回顾】

    罗马数字到整数:

    基本规律,当左边数字大于右边,是和的关系,如VI=5+1=6,XII=10+2=12;

    当左边数字小于右边,是差的关系,如IV=5-1=4,IX=10-1=9,XL=50-10=40.

    【思路1】

    列出字符所有可能的情况成单独一个方法,对string s的每个元素调用方法,得到其代表的值,有三种可能:

    1)连续相等,则累加到临时变量sub

    2)若当前值比前一个值小,则把sub加到result上,再sub=cur

    3)若当前值比前一个值大,则是“含4”情况,就要有sub=cur-lastc

    【other code1】

    int romanToInt(string s) {
        if(s.length() < 1) return 0;  
        int result=0;
        int sub=getthenumber(s[0]);
        int lastc=sub;
        int cur=0;
        for(int i=1;i<s.length();i++)
        {
            cur=getthenumber(s[i]);
            if(cur==lastc)
                sub+=cur;
            else if(cur>lastc)
                sub=cur-sub;
            else {
                result+=sub;
                sub=cur;
            }
               lastc=cur;
        }
        result+=sub;
        return result;  
        }  
        int getthenumber(char c) {  
            switch(c) {  
                case 'I': return 1;   
                case 'V': return 5;  
                case 'X': return 10;  
                case 'L': return 50;  
                case 'C': return 100;  
                case 'D': return 500;  
                case 'M': return 1000;  
                default: return 0;  
            }  
        }  

    【思路2】

    用数组保存特殊字母对应的十进制数,相当于上面的getthenumber函数。

    int romanToInt(string s) {
            int map[26];
            map['I'-'A'] = 1; map['V'-'A'] = 5; map['X'-'A'] = 10; map['L'-'A'] = 50; 
            map['C'-'A'] = 100; map['D'-'A'] = 500; map['M'-'A'] = 1000;
            int res = 0, n = s.size();
            s.push_back(s[n-1]);
            for(int i = 0; i < n; i++)
            {
                if(map[s[i]-'A'] >= map[s[i+1]-'A'])
                    res += map[s[i]-'A'];
                else res -= map[s[i]-'A'];
            }
            return res;
        }

    代码明显要简洁很多,注意最后一位的处理,为了满足比较i+1位。否则会发生越界!

    【本题思路】

    1.因为给出最大值是3999,因此可以从1000开始除,列出每一位所有可能

    string intToRoman(int num) {
            char c[10][10][10]={{"0","I","II","III","IV","V","VI","VII","VIII","IX"},{"0","X","XX","XXX","XL","L","LX"
            ,"LXX","LXXX","XC"},{"0","C","CC","CCC","CD","D",
                  "DC","DCC","DCCC","CM"},{"0","M","MM","MMM"}};
            int t=1;
            int tmp=num;
            string st;
            if(tmp/1000!=0) st+=c[3][tmp/1000];
            if((tmp%1000)/100!=0) st+=c[2][(tmp%1000)/100];
            if((tmp%100)/10!=0) st+=c[1][(tmp%100)/10];
            if(tmp%10!=0) st+=c[0][tmp%10];
            return st;
        }

    2.发现规律:

    个位上的数字依次是 I,II,III,IV,V,VI,VII,VIII,IX

    十位上的数字把I替换为X,V替换为L,X替换为C,即表示10,20,...,90

    百位、千位依次类推。

    【other code】

    string intToRoman(int num) {
            char romanChar[]={'I','V','X','L','C','D','M'};
            string res;
            int i=6,factor=1000;
            while(num!=0){
                helper(num/factor,&romanChar[i],res);
                num%=factor;
                factor/=10;
                i-=2;
            }
            return res;
        }
        void helper(int k, char *romanChar, string &res){
            if(k<=0);
            else if(k<=3)
                res.append(k,romanChar[0]);
            else if(k==4){
                res.push_back(romanChar[0]);
                res.push_back(romanChar[1]);
            }
            else if(k<=8){
                res.push_back(romanChar[1]);
                res.append(k-5,romanChar[0]);
            }
            else if(k==9){
                res.push_back(romanChar[0]);
                res.push_back(romanChar[2]);
            }
        }

    【总结】

    有好几个聪明的处理:

    1.每一位都按照1-9的思路处理,变的是传入的romanChar表,用&romanChar[i]来取特定的子串。i每次-=2.

    2.res.append(int,char)头一次使用,表示在res后接int个相同的char字符,即III类似。

  • 相关阅读:
    PAT-乙级-1011. A+B和C (15)
    PAT-乙级-1010. 一元多项式求导 (25)
    PAT-乙级-1009. *说反话 (20)
    PAT-乙级-1008. 数组元素循环右移问题 (20)
    PAT-乙级-1007. 素数对猜想 (20)
    PAT-乙级-1006. 换个格式输出整数 (15)
    PAT-乙级-1005. 继续(3n+1)猜想 (25)
    PAT-乙级-1004. 成绩排名 (20)
    BZOJ 1030: [JSOI2007]文本生成器
    BZOJ 2938: [Poi2000]病毒
  • 原文地址:https://www.cnblogs.com/ketchups-notes/p/4494095.html
Copyright © 2011-2022 走看看