Roman to Integer python



我正试图用python3解决这个python问题,我的代码看起来是这样的。

class Solution:
def romanToInt(self, s: str) -> int:
# Define integer value to each roman 
rom_val = {'I': 1, 'V': 5, 'X': 10, 'L': 50,
'C': 100, 'D': 500, 'M': 1000}
# A list of integer values
value = list(map(rom_val.get, s))
# The subtracted new number
new = 0
# The converted integer number
integer = 0
# List to keep the checked roman
checked = []
for i, j in enumerate(value):
if j > value[i+1] or j == value[i+1]:
checked.append(j)
if j < value[i+1]:
new = value[i+1] - j
checked.append(new)
return sum(checked)

但是,我在第一个if语句中得到IndexError:list索引超出范围。尽管我知道这是一个相当简单的问题,但我还是有一些不理解的地方。所以我有两个问题:1.当然,为什么我会出现这个索引错误?我该怎么修?2.我解决这个问题的方法正确吗?

非常感谢。

这里有一种不同的方法,5行:

d = {'M':1000, 'D':500, 'C':100, 'L':50, 'X':10, 'V':5, 'I':1}
def romanToInt(self, s):
res, p = 0, 'I'
for c in s[::-1]:
res, p = res - d[c] if d[c] < d[p] else res + d[c], c
return res

基本上,向后看,将每个字母相加得到结果,除非较小的字母在较大的字母前面,在这种情况下是减法而不是加法。


注意:以下不是完整的解决方案,只是对问题中提到的错误的修复。你的算法有一个大错误。

MCMXCIV应该是1994,但它返回3099。这是因为您认为C100M1000,但应该将CM视为900。由于上面有一个解决方案,我将把它作为一个练习留给您

代码的问题是,即使到达最后一个索引,也要检查i + 1。你可以这样修复:

def romanToInt(s: str) -> int:
# Define integer value to each roman 
rom_val = {'I': 1, 'V': 5, 'X': 10, 'L': 50,
'C': 100, 'D': 500, 'M': 1000}
# A list of integer values
value = list(map(rom_val.get, s))
# List to keep the checked roman
checked = []
for i, j in enumerate(value):
if i == len(value) - 1:
checked.append(j)
elif j >= value[i+1]:
checked.append(j)
elif j < value[i+1]:
checked.append(value[i+1] - j)
print(checked)
return sum(checked)
print(romanToInt("LVIII"))

我还使您的代码更加简洁,删除了不必要的变量。主要的变化只是检查它是否是value中的最后一个索引。

我知道这是一篇有答案的帖子,但我想添加3个具有各自运行时的解决方案,将罗马数字转换为数字。

解决方案1:(大约运行时间=52ms(

def romanToInt(self, s: str) -> int:
roman = {'I':1, 'V':5, 'X':10, 'L':50, 'C':100, 'D':500, 'M':1000 }    
num = 0
for i in range(len(s)):
if i!= len(s)-1 and roman[s[i]] < roman[s[i+1]]:
num += roman[s[i]]*-1
else:
num += roman[s[i]]
return num

解决方案2:(近似运行时间=60ms(

def romanToInt(self, s: str) -> int:
roman = {'I':1, 'V':5, 'X':10, 'L':50, 'C':100, 'D':500, 'M':1000 }    
num = 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 x in s:
num += roman[x]
return num

解决方案3:(近似运行时间=48ms(

def romanToInt(self, s: str) -> int:
roman = {'I':1, 'V':5, 'X':10, 'L':50, 'C':100, 'D':500, 'M':1000 }    
num = 0
for i in range(len(s)-1):
if roman[s[i]] < roman[s[i+1]]:
num += roman[s[i]]*-1
continue
num += roman[s[i]]
num +=roman[s[-1]]
return num

最简单的解决方案有时似乎是最好的:(

这个问题可以通过以下想法来解决:罗马数字中的每个罗马数字都按降序排列。如果不是这样,那么它就是一个特例,如"IV"、"IX"、"XL"。。。。。

在下文中,上述特殊情况由if语句处理。

def romanToInt(s):
mapping  = {
'I': 1,
'V': 5,
'X': 10,
'L': 50,
'C': 100,
'D': 500,
'M': 1000,
}

min_ = None
total = 0
for c in s:
val = mapping[c]
print(val)
if min_ and val > min_:
total -= min_*2
else:
min_ = val
total += val

return total

看看这段代码。逻辑很容易理解。

注意:这个想法是以相反的方式逐个字符遍历罗马数字,如果下一个字符大于或等于上一个字符,则进行加法运算。

def romanToDecimal(self, S): 
d = {
'I':1, 'V':5, 'X':10, 'L':50, 'C':100, 'D':500, 'M':1000
}
res = 0
old = 'I'

for i in S[::-1]:
if d[i] >= d[old]:
res = res + d[i]
else:
res = res - d[i]
old = i

return res

例如,在这里,我将'II'传递给函数,使其值变为[1,1]。现在使用enumerate,您将在第二次迭代中使用(1,1(作为i,j,这将导致索引错误。那么你就可以很容易地解决这个问题。

最新更新