力扣-13. 罗马数字转整数(Roman to Integer)

最后编辑于2025-06-16

13. 罗马数字转整数(Roman to Integer)

Easy

罗马数字由七个符号表示:I(1), V(5), X(10), L(50), C(100), D(500), M(1000)。

将给定的罗马数字字符串转换为整数,输入保证在 1 到 3999 范围内且为有效罗马数字。


示例:

  • 输入:"III",输出:3
  • 输入:"IV",输出:4
  • 输入:"IX",输出:9
  • 输入:"LVIII",输出:58(L = 50, V = 5, III = 3)
  • 输入:"MCMXCIV",输出:1994(M = 1000, CM = 900, XC = 90, IV = 4)

约束:

  • 1 <= s.length <= 15
  • s 仅包含字符 I, V, X, L, C, D, M
  • 保证 s 是一个合法的罗马数字(范围 [1,3999])

思路与解法

把罗马数字转为整数的常见技巧是利用映射表(HashMap)把每个字符映射为对应的值,然后从左到右遍历字符串,依据相邻字符的大小关系决定加或减:

  • 若当前字符的值大于或等于下一个字符的值,则把当前值加入结果。
  • 若当前字符的值小于下一个字符的值,则说明需要做减法(例如 IV 中 I 在 V 前面),把当前值从结果中减去。

基于这个规则可以在一次线性扫描内完成转换。也可以采用“前一位比较”的技巧:每次将当前值加到结果上,当发现当前值大于前一位时,说明上一步多加了前一位,需要减去两倍的前一位(等价于做减法)。下面给出两种实现。


方法一:向前看法(加或减)

1
2
3
4
5
6
7
8
9
10
11
12
13
class Solution {
public:
int romanToInt(string s) {
int res = 0;
unordered_map<char, int> m{{'I',1},{'V',5},{'X',10},{'L',50},{'C',100},{'D',500},{'M',1000}};
for (int i = 0; i < s.size(); ++i) {
int val = m[s[i]];
if (i == s.size() - 1 || m[s[i+1]] <= m[s[i]]) res += val;
else res -= val;
}
return res;
}
};
  • 时间复杂度: O(n)
  • 空间复杂度: O(1)(映射表大小固定)

方法二:前一位修正法

1
2
3
4
5
6
7
8
9
10
11
12
class Solution {
public:
int romanToInt(string s) {
int res = 0;
unordered_map<char, int> m{{'I',1},{'V',5},{'X',10},{'L',50},{'C',100},{'D',500},{'M',1000}};
for (int i = 0; i < s.size(); ++i) {
if (i == 0 || m[s[i]] <= m[s[i-1]]) res += m[s[i]];
else res += m[s[i]] - 2 * m[s[i-1]]; // 修正前一步多加的值
}
return res;
}
};
  • 说明: 第二种做法利用前一次累加的值进行修正,逻辑精巧且只需一次遍历。

作者想说的话:
罗马数转整数的关键是利用字符到数值的映射并通过相邻字符大小判断是否执行减法,线性扫描即可完成转换,代码简洁且高效。