1. 题目:

2. 题意分析:
给一个正整数,然后把它对应的每一个位上的数字用相应的罗马数字表示,要注意特殊的那几个的使用(4,9,40,90、、、、)。看到这个题我首先想到的就是以前遇到的一种题目,就是给买东西结账时,有多少种方法(可能表述的不清楚,不是用支付宝、微信什么的。而是假如要支付1元,而你手里的钱有1角,五角,一元的,但是数目不限,问有哪些组合方法)。所以这一次我也是用那个思路来做的。
3. 解法一:
代码:
class Solution:
def intToRoman(self, num):
num = str(num)
num_list = []
num_dict = {"1": "I", "5": "V", "10": "X", "50": "L", "100": "C", "500": "D", "1000": "M",
"4": "IV", "9": "IX", "40": "XL", "90": "XC", "400": "CD", "900": "CM"}
for item in num:
if len(num) != 0:
row = "{0:0<{1}}".format(item, len(num))
if row in num_dict:
num_list.append(num_dict[row])
else:
n = "1"+row[1:] # 例如row是"300", 则n就是100
count = int(row[0]) # 那么count就是3
if count > 5:
count_1 = 5*int(n)
count_2 = count-5
num_list.append("{0}".format(num_dict[str(count_1)]))
num_list.append(count_2*"{}".format(num_dict[n]))
else:
num_list.append(count*"{}".format(num_dict[str(n)]))
num = num[1:]
return "".join(num_list)
执行结果:


时间复杂度是O(n)=n
这儿有几个关键点。
(1)如何通过数字转化为罗马数字,我是选用字典的方法,先推出有哪些组合的方法,然后利用字典检索就可以将对应的罗马数字表示出来。
(2)例如给的数是738,那么我就可以先得到这样的组合(700+30+8),然后又细分得到这个组合(500+100+100+10+10+10+5+1+1+1),然后从字典中寻找出相应的罗马数字,组合成一个字符串就可以了。
接下来就是如何优化。
3.解法二:
代码:
class Solution:
def intToRoman(self, num):
num = str(num)
romes = ""
num_dict = {"1": "I", "5": "V", "10": "X", "50": "L", "100": "C", "500": "D", "1000": "M",
"4": "IV", "9": "IX", "40": "XL", "90": "XC", "400": "CD", "900": "CM"}
for item in num:
if len(num) != 0:
row = "{0:0<{1}}".format(item, len(num))
if row in num_dict:
romes += num_dict[row]
num = num[1:]
continue
n = "1"+row[1:] # 例如row是"300", 则n就是100, 如果row是3,那么n就是1
count = int(row[0]) # 那么count就是3
if count > 5:
count_1 = 5*int(n) # 最高位用5代替,其余的以0代替,例如n=700,那么count_1=500
count_2 = count-5 # 获取n的最高位与5相减的值,例如,n=700,那么count_2=2
romes = romes + "{0}".format(num_dict[str(count_1)]) + count_2*"{}".format(num_dict[n])
num = num[1:]
continue
romes += count*"{}".format(num_dict[str(n)])
num = num[1:]
return romes
执行结果:


时间复杂度还是O(n)=n
代码解释:
(1)这个代码和第一个变化不大,只是将不必要的条件判断语句进行了删改,对比执行结果,效果也不是很明显。
4. 最优解法:
我将已提交结果里的最优解复制了下来进行对比:
class Solution:
def intToRoman(self, num):
res = ''
token = [(1000, 'M'), (900, 'CM'), (500, 'D'), (400, 'CD'), (100, 'C'), (90, 'XC'), (50, 'L'), (40, 'XL'), (10, 'X'), (9, 'IX'), (5, 'V'), (4, 'IV'), (1, 'I')]
for n, t in token:
while num >= n:
res += t;
num -= n
return res
执行用时是116ms。而且人家这个代码量。。。。。
5.总结:
最近好像有点思维定式了,老是一看到整数就想着转化为字符串来处理,但是几次相同的经历表明,python处理数字比字符串、列表等要快的多。