问题概述
给定一个罗马数字字符串,将其转换为整数。
罗马数字由七个符号表示,其值为:
I= 1,V= 5,X= 10,L= 50,C= 100,D= 500,M= 1000
罗马数字通常从大到小从左到右书写。但是,在六种情况下使用减法:
IV= 4,IX= 9XL= 40,XC= 90CD= 400,CM= 900
解法 1:从左到右带前瞻
工作原理
从左到右处理字符串,检查当前符号的值是否小于下一个符号的值:
python
class Solution:
def romanToInt(self, s):
roman_map = {
'I': 1, 'V': 5, 'X': 10, 'L': 50,
'C': 100, 'D': 500, 'M': 1000
}
total = 0
i = 0
n = len(s)
while i < n:
if i < n - 1 and roman_map[s[i]] < roman_map[s[i + 1]]:
total += roman_map[s[i + 1]] - roman_map[s[i]]
i += 2
else:
total += roman_map[s[i]]
i += 1
return total
复杂度分析
- 时间复杂度: O(n) - 单次遍历字符串
- 空间复杂度: O(1) - 只使用常数额外空间
何时使用
- 直观的从左到右处理
- 易于理解的逻辑
解法 2:从右到左(推荐)
工作原理
从右到左处理字符串。如果当前值小于前一个值,则减去;否则加上:
python
class Solution:
def romanToInt(self, s):
roman_map = {
'I': 1, 'V': 5, 'X': 10, 'L': 50,
'C': 100, 'D': 500, 'M': 1000
}
total = 0
prev_value = 0
for char in reversed(s):
current_value = roman_map[char]
if current_value < prev_value:
total -= current_value
else:
total += current_value
prev_value = current_value
return total
关键洞察
当从右到左处理时,如果我们遇到一个较小的值后跟一个较大的值(在原始从左到右的顺序中),这意味着我们应该减去。通过从右到左,我们自然检测到这一点:如果 current_value < prev_value,当前字符在较大的字符之前,所以我们减去。
复杂度分析
- 时间复杂度: O(n) - 单次遍历字符串
- 空间复杂度: O(1) - 常数额外空间
何时使用
- 推荐 - 实际情况下最快
- 简洁优雅的逻辑
- 无需检查下一个字符的边界
对比
| 方法 | 时间 | 空间 | 最佳适用 |
|---|---|---|---|
| 从左到右 | O(n) | O(1) | 直观处理 |
| 从右到左 | O(n) | O(1) | 大多数情况,最快 |
总结
从右到左方法是最快且最优雅的解决方案。它通过从末尾处理自然地处理减法情况,避免了前瞻的需要。两种方法具有相同的时间复杂度,但从右到左在实际情况下表现最佳。