题目描述:罗马数字包含以下七种字符: I
, V
, X
, L
,C
,D
和 M
。
字符 数值 I 1 V 5 X 10 L 50 C 100 D 500 M 1000
例如, 罗马数字 2
写做 II
,即为两个并列的 1 。12
写做 XII
,即为 X
+ II
。 27
写做 XXVII
, 即为 XX
+ V
+ II
。
通常情况下,罗马数字中小的数字在大的数字的右边。但也存在特例,例如 4 不写做 IIII
,而是 IV
。数字 1 在数字 5 的左边,所表示的数等于大数 5 减小数 1 得到的数值 4 。同样地,数字 9 表示为 IX
。这个特殊的规则只适用于以下六种情况:
I
可以放在V
(5) 和X
(10) 的左边,来表示 4 和 9。X
可以放在L
(50) 和C
(100) 的左边,来表示 40 和 90。C
可以放在D
(500) 和M
(1000) 的左边,来表示 400 和 900。
给定一个罗马数字,将其转换成整数。
解题思路:
① 我们首先把题目中给出的罗马字符和数字的对应关系存入哈希表中。
② 通常情况下,直接把读取到的当前罗马字符对应的字符加入sum值;
存在6种特殊情况:IV,IX,XL,XC,CD,CM,它们的共同之处在于左边的数字比右边的大,也就是map[s[i]] < map[s[i+1]];而通常情况下则满足map[s[i]] >=map[s[i+1]],我们可以将此作为if-else语句的条件分开处理。
③ if-else语句内部的编写:
观察题目给出的特殊情况中的双字母组合,可以发现右边的字符对应值正常相加(sum += m[s[i]]),左边的字符对应值不加反减(sum += -m[s[i]])。那么这一部分也就解决了。
代码展示,时间复杂度和空间复杂度都不太好。。。还有很多可以优化的地方
class Solution {
public:
int romanToInt(string s) {
//构建哈希表
unordered_map<char, int> m = {
{'I', 1},
{'V', 5},
{'X', 10},
{'L', 50},
{'C', 100},
{'D', 500},
{'M', 1000}
};
int sum = 0;
int i;
for(i=0; i<s.length(); i++)
{
//i为左字符(当前字符),j为右字符
int j = i+1;
// cout << s[i] << s[j] << sum << endl;
//注意处理到最后一个字符时不要越界
if(m[s[i]] < m[s[j]] && j<s.length())
{
//sum的加数不是s[i](char)也不是m[i](key),多次尝试后才发现是value
sum += -m[s[i]];
}else{
sum += m[s[i]];
}
}
return sum;
}
};