leetcode 13. Roman to Integer
Roman numerals are represented by seven different symbols:
I
,V
,X
,L
,C
,D
andM
.Symbol Value I 1 V 5 X 10 L 50 C 100 D 500 M 1000For example, two is written as
II
in Roman numeral, just two one's added together. Twelve is written as,XII
, which is simplyX
+II
. The number twenty seven is written asXXVII
, which isXX
+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 asIV
. Because the one is before the five we subtract it making four. The same principle applies to the number nine, which is written asIX
. There are six instances where subtraction is used:
I
can be placed beforeV
(5) andX
(10) to make 4 and 9.X
can be placed beforeL
(50) andC
(100) to make 40 and 90.C
can be placed beforeD
(500) andM
(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: 3Example 5:
Input: "MCMXCIV" Output: 1994 Explanation: M = 1000, CM = 900, XC = 90 and IV = 4.
解决思路:
将问题分解成: 解决一个字母和两个以上字母 ---> 两个以上字母分成只有加法 和 有减法 的字符串
对于减法,另开一个数组记录减法的具体位置,那个位置直接乘上 -1 再一起加
代码如下:
class Solution(object):
def romanToInt(self, s):
"""
:type s: str
:rtype: int
"""
result = 0
d = {'I':1, 'V':5, 'X':10, 'L':50, 'C':100, 'D':500, 'M':1000}
PLUS = True
minusFlag = [1]*len(s) # record the position of minus
if(len(s)==1):
return d[s[0]]
else:
for i in range(len(s)-1):
if(d[s[i]] < d[s[i+1]]):
PLUS = False
minusFlag[i] = -1
#have two char
if (PLUS) :
#add, count the number of each char
for i in d.keys():
result = result + s.count(i) * d[i]
return result
else:
#minus
for i in range(len(s)):
result = d[s[i]] * minusFlag[i] + result
return result
一次过了,跑得速度挺快的,第一次99.8%,有点小激动。后来发现想复杂了,其实不需要分成加和减的两个分支,以下是短一些的代码:
class Solution(object):
def romanToInt(self, s):
result = 0
d = {'I':1, 'V':5, 'X':10, 'L':50, 'C':100, 'D':500, 'M':1000}
minusFlag = [1]*len(s) # record the position of minus
if(len(s)==1):
return d[s[0]]
else:
for i in range(len(s)-1):
if(d[s[i]] < d[s[i+1]]):
minusFlag[i] = -1
for i in range(len(s)):
result = d[s[i]] * minusFlag[i] + result
return result
之后看Dicsussion, 看到有些有趣的解法:
解法1.全部加起来,然后遇到减的地方直接减两次:
def romanToInt(self, s):
value, prevValue, result = {'M': 1000, 'D': 500, 'C': 100, 'L': 50, 'X': 10, 'V': 5, 'I': 1}, None, 0
for ch in s:
currValue = value[ch]
result += currValue
if prevValue and currValue > prevValue: result -= 2 * prevValue
prevValue = currValue
return result
2.直接替换减法的地方,换成加法的字符(真心Amazing了):
class Solution:
def romanToInt(self, s: str) -> int:
translations = {
"I": 1,
"V": 5,
"X": 10,
"L": 50,
"C": 100,
"D": 500,
"M": 1000
}
number = 0
s = s.replace("IV", "IIII").replace("IX", "VIIII")
s = s.replace("XL", "XXXX").replace("XC", "LXXXX")
s = s.replace("CD", "CCCC").replace("CM", "DCCCC")
for char in s:
number += translations[char]
return number
3. 先翻转整个字符串,如果碰到比现在得到的数小5倍的就是减法操作的数值(这个观察力好强鸭),代码如下:
class Solution:
# @return an integer
def romanToInt(self, s):
result=0
dic={'I':1,'V':5,'X':10,'L':50,'C':100,'D':500,'M':1000}
for i in s[::-1]:
symbol=1
if (i in ['I','X','C']) and result>=5*dic[i]:
symbol=-1
result+=dic[i]*symbol
return result