题目:
Leetcode
等级easy
:
Roman numerals are represented by seven different symbols: I, V, X, L, C, D and M
.
Symbol Value
I 1
V 5
X 10
L 50
C 100
D 500
M 1000
For example, two
is written as II
in Roman numeral, just two one’s added together. Twelve
is written as, XII
, which is simply X + II
. The number twenty seven
is written as XXVII
, which is XX + V + II
.
Roman numerals are usually written largest to smallest from left to right. However, the numeral for four
is not IIII
. Instead, the number four
is written as IV
. Because the one is before the five we subtract it making four. The same principle applies to the number nine
, which is written as IX
. There are six instances where subtraction is used:
I can be placed before V (5) and X (10) to make 4 and 9.
X can be placed before L (50) and C (100) to make 40 and 90.
C can be placed before D (500) and M (1000) to make 400 and 900.
Given a roman numeral, convert it to an integer. Input is guaranteed to be within the range from 1 to 3999
.
Example 1:
Input: "III"
Output: 3
Example 2:
Input: "IV"
Output: 4
Example 3:
Input: "IX"
Output: 9
Example 4:
Input: "LVIII"
Output: 58
Explanation: L = 50, V= 5, III = 3.
Example 5:
Input: "MCMXCIV"
Output: 1994
Explanation: M = 1000, CM = 900, XC = 90 and IV = 4.
分析及思路:
首先对题目做分析如下:
总的来说,罗马数字不外乎这几种组合方式:第一种是几个相同的组合如III
,II
分别代表3
和2
,第二种是较小数在较大数右侧组合如VI
, XII
分别代表6
和12
,第三种是较小数在左侧的组合如IV
,IX
分别代表4
和9
,还有一种是单个判断,一个符号代表一个数。
如果我们统一按照从左到右的方式计算总和,那么在这四种组合方式中,第一种、第二种都是可以通过最后一种方法计算得到的,单个获取值相加即可。也就是说只需要考虑两种情况:一种是单个符号的情况,一种是较小数在左侧的情况。
接下来便是选择实现方法了,好的方法可以节省代码量,并具有更高的速度:
自己对字符串操作比较熟悉,而且字符串处理也很快,所以类似的题目,第一想法就是用字符串方法实现。一开始是想构建一堆if-elif-else
,只需要把每种情况囊括进去就ok,写了一半感觉太乱了,于是选用字符串函数直接替换符合条件的值,最后统一为列表依次取值计算。
还有一种方法,既然这里面有映射关系,那哈希就应该被想到,python
中有现成的数据结构:字典,从这个角度也是有一种方法能解的,速度应该更加快。
代码:
利用字符串函数和列表实现:
class Solution:
def romanToInt(self, x):
"""
:type x: str
:rtype: int
"""
res = 0
# 2位不同
x = x.replace('IV', '4,')
x = x.replace('IX', '9,')
x = x.replace('XL', '40,')
x = x.replace('XC', '90,')
x = x.replace('CD', '400,')
x = x.replace('CM', '900,')
# 1位
x = x.replace('I', '1,')
x = x.replace('V', '5,')
x = x.replace('X', '10,')
x = x.replace('L', '50,')
x = x.replace('C', '100,')
x = x.replace('D', '500,')
x = x.replace('M', '1000,')
l = x.rstrip(',').split(',')
for each in l:
res += int(each)
return res
利用字典实现:
class Solution:
def romanToInt(self, x):
"""
:type x: str
:rtype: int
"""
i = 0
res = 0
one_dict = {'I':1, 'V':5, 'X':10, 'L':50, 'C':100, 'D':500, 'M':1000}
two_dict = {'IV':4, 'IX':9, 'XL':40, 'XC':90, 'CD':400, 'CM':900}
while i<len(x):
if x[i:i+2] in two_dict:
res += two_dict[x[i:i+2]]
i += 2
else:
res += one_dict[x[i]]
i += 1
return res
总结:
由于运行耗时感觉误差太大了,没什么意义,就不再贴图了,以实际运行时为准。
这个题目用hash
的方式感觉是更好的,不过无论是哪种方法,总体思路的核心是一个映射关系,只要分析清楚映射关系,代码是比较好构思的,而且速度也不会相差太大。