在问 · 算法题解

13. 罗马数字转整数

题目描述

罗马数字由七个符号组成:I=1,V=5,X=10,L=50,C=100,D=500,M=1000。

一般写法是大的符号在左、小的在右,数值相加,比如 XII = 12,XXVII = 27。

有六种减法写法,小符号放在大符号左侧时用大数减小数:IV=4,IX=9,XL=40,XC=90,CD=400,CM=900。

输入一个罗马数字字符串 s,返回它代表的整数。

示例 1
输入:s = "III"
输出:3

解释:三个 I 相加得 3。

示例 2
输入:s = "LVIII"
输出:58

解释:L = 50,V = 5,III = 3,合计 58。

示例 3
输入:s = "MCMXCIV"
输出:1994

解释:M = 1000,CM = 900,XC = 90,IV = 4,合计 1994。

数据范围

  • 1 <= s.length <= 15
  • s 只含字符 I、V、X、L、C、D、M。
  • s 一定是合法的罗马数字,表示的值在 [1, 3999] 之间。
  • 输入遵守标准写法,不会出现 IL、IM 这类跨位的减法;例如 49 写作 XLIX,999 写作 CMXCIX。

解题思路

从左到右看每个符号:如果它比右边一个符号小,它就是减法形式中被减的那一项,应该减去;否则加上。例如 CM:C < M,先减 100,再加 1000,得到 900。最后一个符号右边没有符号,总是加上。

为什么正确

处理完前 i 个符号后,ans 等于这些符号带符号贡献之和;负贡献总会在下一步被更大的正贡献抵消。

复杂度分析

时间 O(n),空间 O(1)。

易错点

比较的是“当前符号与右侧邻居”,而不是与左侧;如果想用左侧比较,就得在发现大符号时补减两倍的前一项,容易写错。另外访问 s[i+1] 前要先判断 i+1 没有越界。

参考代码

Python、Java、C++、Go、JavaScript、TypeScript 六种语言,逻辑一致。

class Solution:
    def romanToInt(self, s: str) -> int:
        val = {'I': 1, 'V': 5, 'X': 10, 'L': 50, 'C': 100, 'D': 500, 'M': 1000}
        ans = 0
        for i, c in enumerate(s):
            v = val[c]
            if i + 1 < len(s) and v < val[s[i + 1]]:
                ans -= v
            else:
                ans += v
        return ans

载入编辑器,自己跑一遍 →

字符串 专题的其他题目

查看 字符串 全部题目 →