我正试图用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
。这是因为您认为C
是100
,M
是1000
,但应该将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,这将导致索引错误。那么你就可以很容易地解决这个问题。