
本文详解罗马数字转整数的正确实现逻辑,指出常见错误(如索引越界、减法规则误判),提供简洁可靠的算法实现,并对比第三方库方案,兼顾教学性与工程实用性。
本文详解罗马数字转整数的正确实现逻辑,指出常见错误(如索引越界、减法规则误判),提供简洁可靠的算法实现,并对比第三方库方案,兼顾教学性与工程实用性。
罗马数字转整数是经典的字符串解析问题,核心在于理解其“左减右加”规则:当较小值符号出现在较大值符号左侧时(如 IV、IX、XL、XC、CD、CM),需执行减法;其余情况累加即可。原代码存在多处逻辑缺陷:
- 错误使用 list(dic.keys()).index(s[i]) 动态查找索引,导致 next_symbol 和 next2_symbol 与实际后续字符无关;
- string.remove(i) 破坏遍历索引稳定性,引发跳过字符或 IndexError;
- 条件判断冗余且语义混乱(如 s[i] == next_symbol or s[i] == next2_symbol 永远为 False);
- 未校验 i+1 是否越界,直接访问 s[i+1] 导致崩溃风险。
✅ 推荐采用从右向左扫描 + 状态记录的稳健解法:
def romanToInt(s: str) -> int:
dic = {'I': 1, 'V': 5, 'X': 10, 'L': 50,
'C': 100, 'D': 500, 'M': 1000}
result = 0
prev_value = 0
# 从右往左遍历
for char in reversed(s):
curr_value = dic[char]
if curr_value < prev_value:
result -= curr_value # 出现减法规则(如 IV 中 I < V)
else:
result += curr_value
prev_value = curr_value
return result
# 测试
print(romanToInt("MCMXCIV")) # 输出:1994
print(romanToInt("LVIII")) # 输出:58
print(romanToInt("IX")) # 输出:9
? 关键原理:
- 右侧字符决定当前位是加还是减;
- 若当前值 小于 左侧已处理的最大值(即 prev_value),说明它属于减法组合的左操作数(如 C 在 CM 中),应减去;
- 否则累加。该逻辑天然覆盖所有合法罗马数字组合,无需硬编码特殊规则。
⚠️ 注意事项:
- 输入应为有效罗马数字字符串(本题默认合法,生产环境建议先校验格式);
- 字典使用 dict 直接映射,避免 zip 构建和重复 list(dic.keys()) 调用,提升性能;
- reversed() 不生成新列表,空间复杂度 O(1)。
? 替代方案(快速落地):
若项目允许引入第三方依赖,roman 库简洁可靠:
pip install roman
import roman
print(roman.fromRoman("MCMXCIV")) # 1994
但需注意:该库不校验非法输入(如 “IIII” 或 “VV”),且增加外部依赖。学习场景建议手写算法以深入理解规则;工程场景可权衡开发效率与可控性。
总结:掌握“右到左扫描 + 比较前值”这一模式,既能写出健壮代码,也便于扩展支持更多符号或自定义规则。
文章来自机圈观察员网,发布者:,转载请注明出处:https://www.jqgcy.com/jiquanzatan/127041.html