题目来源:
题目分析:
1.罗马数字介绍
本题需要对题目意思进行一定的解读,首先需要了解罗马数字的计数情况。
罗马数字共有7个,即I(1)、V(5)、X(10)、L(50)、C(100)、D(500)和M(1000)。按照下述的规则可以表示任意正整数。需要注意的是罗马数字中没有“0”,与进位制无关。一般认为罗马数字只用来记数,而不作演算。
重复数次:一个罗马数字重复几次,就表示这个数的几倍。
右加左减:在较大的罗马数字的右边记上较小的罗马数字,表示大数字加小数字。在较大的罗马数字的左边记上较小的罗马数字,表示大数字减小数字。
(1)左减的数字有限制,仅限于I、X、C。比如45不可以写成VL,只能是XLV。
(2)但是,左减时不可跨越一个位数。比如,99不可以用IC(100 - 1)表示,而是用XCIX([100 - 10] + [10 - 1])表示。(等同于阿拉伯数字每位数字分别表示。)
(3)左减数字必须为一位,比如8写成VIII,而非IIX。
(3)左减数字必须为一位,比如8写成VIII,而非IIX。
(4)右加数字不可连续超过三位,比如14写成XIV,而非XIIII。(见下方“数码限制”一项。)
这里要注意将last设置为None,它是一种特殊的数据类型,代表一个空值而不能认为它是0,因为0是有意义的。你可以将None赋值给任何对象,也可以将任何变量赋值给一个None值的对象。而判断得等last有值了再进行判断。
加线乘千:在罗马数字的上方加上一条横线或者加上下标的Ⅿ,表示将这个数乘以1000,即是原数的1000倍。同理,如果上方有两条横线,即是原数的1000000(1000^{2})倍。
数码限制:同一数码最多只能出现三次,如40不可表示为XXXX,而要表示为XL。
2.本题思路:
由于在较大罗马数字的右边记上一个较小的罗马数字,表示大数字加上小数字,我们可以将罗马字符先进行翻转,从小数字开始相加,如果不存在相减的情况,则应该是从小到大排列的,例如(VI V=5,I=1,VI=6,将其翻转过来叠加也是6)。如果原数字是相减的情况,例如(IV V=5,I=1,IV=5-1=4),则将其翻转时变成了(VI)先叠加了V,如果不采取措施,则下一步会叠加I,造成答案的错误,因此这里我们可以使用一个变量last将每次叠加的数字记录下来,这里是记录V,如果下一次的变量小于这次的(这里指I)。则可以减去2倍的该变量(I),然后将该变量给累加上,相当于做了减法。这种方法比较巧妙,值得学习!!
3.实验结果:
class Solution:
def romanToInt(self, s):
"""
:type s: str
:rtype: int
"""
dic={"M": 1000, "D": 500, "C": 100, "L": 50, "X": 10, "V": 5, "I": 1}
last=None
s=s[::-1]
sum=0
for key in s:
if (last and dic[key]<last):
sum-=2*dic[key]
sum+=dic[key]
last=dic[key]
return sum
这里要注意将last设置为None,它是一种特殊的数据类型,代表一个空值而不能认为它是0,因为0是有意义的。你可以将None赋值给任何对象,也可以将任何变量赋值给一个None值的对象。而判断得等last有值了再进行判断。