[&] () {}

Life is short , Import your DREAM.独学无友,则孤陋而难成;久处一方,则习染而不自觉。...

LeetCode之Roman & Integer 的转换(简单题)

罗马数字和现在使用的阿拉伯整数之间的转换在LeetCode上一共有两道题目:Roman to Integer 和Integer to Roman
如标题所说的,这是个简单的字符串处理的题目,基本上知道了规则就可以直接写出代码解决了。

罗马数字基本规则

做好这道题目的前提是知道一些罗马数字的基本规则。
罗马数字一共有七个,分别是I(1)、V(5)、X(10)、L(50)、C(100)、D(500)和M(1000)。
按照下面的规则就可以表示所有的正整数了。需要注意的是罗马数字中没有“0”,也与进位制无关,所以,一般是将罗马数字用来记数,不用于演算。

重复次数:一个罗马数字重复几次就表示是其几倍。比如II表示2
右加左減:在较大的罗马数字右边记上一个较小的罗数字,则其表示的数字是大数减去小数的结果,比如IV表示4。在较大的罗马数字左边记上一个较小的罗数字,则其表示的数字是大数加上小数的结果,比如VI表示6。需要注意的是:左减的数字有限制,仅限于I、X、C。比如45不可以写成VL,只能是XLV。
同时,左减的时候不可以跨越数位。比如,99不可以用IC(100 - 1)表示,而是用XCIX([100 - 10] + [10 - 1])表示。(就是把每位阿拉伯数字逐位表示。)
左减数字必须是一位,比如8是VIII,而不是IIX。
右加的数字也不可以连续超过三位,比如14是XIV,而非XIIII。(即是有数位限制。)
加线成千:
在罗马数字的上方加上一条横线或者加上下标的Ⅿ,表示将这个数字乘以1000,即是原数的1000倍。
同理,如果上方有两条横线,即是原数字的1000000(1000^{2})倍。
数位限制:
同一数位最多只能出現三次,如40不可表示为XXXX,而要表示为XL。
例外:由于IV是古罗马神话主神朱庇特(即IVPITER,古罗马字母沒有J和U)的首字,因此有时用IIII代替Ⅳ。

Roman to Integer

有了罗马数字的基本概念(其实只要知道罗马数字的基本表示位就可以做这道题目了,但是多了解些也没有什么坏处 :P),下面就看下如何做这道题目,首先是罗马数字转阿拉伯数字。

3999范围内的罗马数字不会用到加上划线的字母

从最后一个字符开始,如果当前字符对应的数字比上一个数字小,那么就把结果减去当前字符对应的数字,否则加上当前字符对应数字。为了处理边界情况,在原字符串最后添加一个字符,该字符是原来的尾字符。

class Solution {
public:
    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;
    }
};

另一种解法:

class Solution {
public:
    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;
    }
};

Integer to Roman

整数转罗数字就更简单了,直接把整数从前向后逐位提出,然后按照其所在的位替换对应的罗马数字表示即可,如下:

class Solution {
public:
    string intToRoman(int num) {
            string roman[4][10] = {
            {"", "I", "II", "III", "IV", "V", "VI", "VII", "VIII", "IX"},
            {"", "X", "XX", "XXX", "XL", "L", "LX", "LXX", "LXXX", "XC"},
            {"", "C", "CC", "CCC", "CD", "D", "DC", "DCC", "DCCC", "CM"},
            {"", "M", "MM", "MMM"}
        };

        string ret = "";
        int digit = 0;
        while (num != 0) {
            int remain = num % 10;
            ret = roman[digit][remain] + ret;
            digit++;
            num /= 10;
        }

        return ret;
    }
};

另一个更简洁的解法:
这本题目中,整个罗马数字的表示体系就是由1,4,5,9,10,40,50,90,100,400,500,900,1000这些构成的
,理解了规则之后就可以这要写了。

class Solution {
public:
    string intToRoman(int num) {
        string str;  
        string symbol[]={"M","CM","D","CD","C","XC","L","XL","X","IX","V","IV","I"};  
        int value[]=    {1000,900,500,400, 100, 90,  50, 40,  10, 9,   5,  4,   1}; 
        for(int i=0;num!=0;++i)
        {
            while(num>=value[i])
            {
                num-=value[i];
                str+=symbol[i];
            }
        }
        return str;
    }
};
阅读更多
所属专栏: LeetCode解题记录
上一篇【Cocos游戏实战】功夫小子第六课之游戏主功能场景的分析和实现
下一篇LeetCode之LCP(Longest Common Prefix)问题
想对作者说点什么? 我来说一句

没有更多推荐了,返回首页

关闭
关闭