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

来源:互联网 发布:centos 6.5搭建lnmp 编辑:程序博客网 时间:2024/05/18 18:18

罗马数字和现在使用的阿拉伯整数之间的转换在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;    }};
1 0
原创粉丝点击