问题
Given a roman numeral, convert it to an integer.
Input is guaranteed to be within the range from 1 to 3999.
例子
2017
MMXVIII
分析
- 方法一:可以参考12. Integer to Roman映射表的思路,建立罗马数字到阿拉伯数字的映射表。映射表中的罗马数字的顺序从大到小排序。遍历并切割字符串,依次和映射表中的罗马数字匹配,把匹配结果累加即可。映射表如下:
vector<pair<string, int>> s2i{{"MMM", 3000}, {"MM", 2000}, {"M", 1000},
{"CM", 900}, {"DCCC", 800}, {"DCC", 700}, {"DC", 600}, {"D", 500}, {"CD", 400}, {"CCC", 300}, {"CC", 200}, {"C", 100},
{"XC", 90}, {"LXXX", 80}, {"LXX", 70}, {"LX", 60}, {"L", 50}, {"XL", 40}, {"XXX", 30}, {"XX", 20}, {"X", 10},
{"IX", 9}, {"VIII", 8}, {"VII", 7}, {"VI", 6}, {"V", 5}, {"IV", 4}, {"III", 3}, {"II", 2}, {"I", 1}
};
- 方法二:映射表不需要那么大,只要保存M D C L X V I这七个基本罗马数字和阿拉伯数字的对应关系就可以了:
unordered_map<char, int> s2i{{'M', 1000}, {'D', 500}, {'C', 100}, {'L', 50}, {'X', 10}, {'V', 5}, {'I', 1}};
然后逐字符遍历字符串,也不需要切割字符串。判断当前字符是不是比下一个字符要对应的阿拉伯数字要大,如果大,就加上当前字符对应的阿拉伯数字;否则减。
要点
- 罗马数字最混淆不清的就是CM(900) XL(40) IV(4)这些数字,涉及到大位数字减去小位数字;
- c++的字符串处理,不得不说,真的很烂。。。
时间复杂度
O(n),n为罗马数字长度。实际上这个数字很短,3999对应的罗马数字MMMCMXCIX才9位数字,所以时间复杂度几乎为O(1).
空间复杂度
O(1)
代码
方法一
class Solution {
public:
int romanToInt(string s) {
vector<pair<string, int>> s2i{{"MMM", 3000}, {"MM", 2000}, {"M", 1000},
{"CM", 900}, {"DCCC", 800}, {"DCC", 700}, {"DC", 600}, {"D", 500}, {"CD", 400}, {"CCC", 300}, {"CC", 200}, {"C", 100},
{"XC", 90}, {"LXXX", 80}, {"LXX", 70}, {"LX", 60}, {"L", 50}, {"XL", 40}, {"XXX", 30}, {"XX", 20}, {"X", 10},
{"IX", 9}, {"VIII", 8}, {"VII", 7}, {"VI", 6}, {"V", 5}, {"IV", 4}, {"III", 3}, {"II", 2}, {"I", 1}
};
int res = 0;
for (size_t i = 0; i < s.size();) {
for (size_t j = 0; j < s2i.size(); j++) {
if (i + s2i[j].first.size() > s.size()) continue;
string roman = s.substr(i, s2i[j].first.size());
if (roman == s2i[j].first) {
res += s2i[j].second;
i += s2i[j].first.size();
break;
}
}
}
return res;
}
};
方法二
class Solution {
public:
int romanToInt(string s) {
unordered_map<char, int> s2i{{'M', 1000}, {'D', 500}, {'C', 100}, {'L', 50}, {'X', 10}, {'V', 5}, {'I', 1}};
int res = 0;
for (int i = 0; i < s.length() - 1; i++) {
if (s2i[s[i]] < s2i[s[i + 1]])
res -= s2i[s[i]];
else
res += s2i[s[i]];
}
res += s2i[s.back()];
return res;
}
};