1. 题目
罗马数字包含以下七种字符: 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。 给定一个罗马数字,将其转换成整数。输入确保在 1 到 3999 的范围内。
示例 1: 输入: "III" 输出: 3
示例 2: 输入: "IV" 输出: 4
示例 3: 输入: "IX" 输出: 9
示例 4: 输入: "LVIII" 输出: 58 解释: L = 50, V= 5, III = 3.
示例 5: 输入: "MCMXCIV" 输出: 1994 解释: M = 1000, CM = 900, XC = 90, IV = 4.
提示:
题目所给测试用例皆符合罗马数字书写规则,不会出现跨位等情况。 IC 和 IM 这样的例子并不符合题目要求,49 应该写作 XLIX,999 应该写作 CMXCIX 。 关于罗马数字的详尽书写规则,可以参考 罗马数字 - Mathematics 。
来源:力扣(LeetCode) 链接:https://leetcode-cn.com/problems/roman-to-integer 著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
2. 解题思路
注意这句话:通常情况下,罗马数字中小的数字在大的数字的右边
因此只要比较两个相邻的字母(数字)
- 如果右边的数字小(级别低)于左边的数字,则说明是通常情况,加上对应的值即可;
- 如果右边的数字大(级别高)于左边的数字,则是特殊情况(共六种),特殊处理即可。注意,每次特殊情况仅涉及到2个数字。
(后面看题解才注意到,这里的情况是: 通常情况 加,特殊情况 减。如:IV = 5-1 =4,VI= 5+1 =6。 )
3. 代码
3.1. AC代码
写复杂了。但范围更广。
class Solution {
public:
int getLevel(char c){
if(c=='I') return 1;
else if(c=='V'||c=='X') return 2;
else if(c=='L'||c=='C') return 3;
else if(c=='D'||c=='M') return 4;
return 0;
}
int getValue(char c){//normal case
int res=0;
switch (c){
case 'I':res=1;break;
case 'V':res=5;break;
case 'X':res=10;break;
case 'L':res=50;break;
case 'C':res=100;break;
case 'D':res=500;break;
case 'M':res=1000;break;
}
return res;
}
int getSpecialValue(char a,char b){//when a's level < b's level
if(a=='I'){
if(b=='V') return 4;
else if(b=='X') return 9;
}else if(a=='X'){
if(b=='L') return 40;
else if(b=='C') return 90;
}else if(a=='C'){
if(b=='D') return 400;
else if(b=='M') return 900;
}
return 0;
}
int romanToInt(string s) {
int res=0,len=s.size();
for(int i=0;i<len;++i){
if(i==len-1||getLevel(s[i])>=getLevel(s[i+1]))
res+=getValue(s[i]);
else res+=getSpecialValue(s[i],s[i+1]),i++;
}
return res;
}
};