> 文章列表 > 12. 整数转罗马数字

12. 整数转罗马数字

12. 整数转罗马数字

题目

罗马数字包含以下七种字符:I,V,X,L,C,D和MI, V, X, L,C,D 和 MIVXLCDM
例如, 罗马数字 222 写做 IIIIII ,即为两个并列的 111121212 写做 XIIXIIXII ,即为 X+IIX + IIX+II 。 $27 $写做 XXVIIXXVIIXXVII, 即为 XX+V+IIXX + V + IIXX+V+II
通常情况下,罗马数字中小的数字在大的数字的右边。但也存在特例,例如 444 不写做 IIIIIIIIIIII,而是 IVIVIV。数字 111 在数字 555 的左边,所表示的数等于大数 555 减小数 111 得到的数值 444 。同样地,数字 999 表示为 IXIXIX。这个特殊的规则只适用于以下六种情况:
III 可以放在 V(5)V (5)V(5)X(10)X (10)X(10) 的左边,来表示 444999
XXX 可以放在 L(50)L (50)L(50)C(100)C (100)C(100) 的左边,来表示 404040909090
CCC 可以放在 D(500)D (500)D(500)M(1000)M (1000)M(1000) 的左边,来表示 400400400900900900
给你一个整数,将其转为罗马数字。

例子

  1. 输入: num=58num = 58num=58
    输出: “LVIII"“LVIII"LVIII"
    解释: L=50,V=5,III=3.L = 50, V = 5, III = 3.L=50,V=5,III=3.
  2. 输入: num=1994num = 1994num=1994
    输出: "MCMXCIV""MCMXCIV""MCMXCIV"
    解释: M=1000,CM=900,XC=90,IV=4.M = 1000, CM = 900, XC = 90, IV = 4.M=1000,CM=900,XC=90,IV=4.

思路

1. 愚蠢的暴力解法

思路大概就是除以10,挨个将每个位上的数字表示出来。比如198419841984分为100010001000900900900808080444

  • 时间复杂度O(n)O(n)O(n)
  • 空间复杂度:O(n)O(n)O(n)
class Solution:def intToRoman(self, num: int) -> str:dict = {'IV': 4, 'V': 5, 'IX': 9, 'XL': 40, 'L': 50, 'XC': 90, 'CD': 400, 'D': 500, 'CM': 900, 'M': 1000}nums = str(num)l = []for i in range(len(nums)):a = (num % 10) * 10iif a in [1, 2, 3]:# Python 会将 a 转换为整型,然后再进行整数除法运算。l.append('I' * a)elif a in [6, 7, 8]:b = a - 5l.append('V' + 'I' * b)elif a in [10, 20, 30]:l.append('X' * (a // 10))elif a in [60, 70, 80]:b = a - 50l.append('L' + 'X' * (b // 10))elif a in [100, 200, 300]:l.append('C' * (a // 100))elif a in [600, 700, 800]:b = a - 500l.append('D' + 'C' * (b // 100))elif a in [1000, 2000, 3000]:l.append('M' * (a // 1000))else:# 这里的 d.items() 方法返回一个可迭代的键值对对象,对于每个键值对 (k, v),如果值 v 等于目标值 target,则返回对应的键 k。for k, v in dict.items():if v == a:l.append(k)breaknum = num // 10output = ''while l:output += l.pop()return output

2. 聪明的暴力解法

这个思路相对比较简单,因为题目中说输入在 139991 ~39991 3999 的范围内,所以我们把 1到9,10到90,100到900,1000到30001 到 9,10 到 90,100 到 900,1000 到 300019109010090010003000 对应的罗马数字都表示出来,最后对于任何输入,我们要做的就是把找到的罗马数字组合起来即可。

比如输入是 235923592359,我们找到 2000,300,50,92000,300,50,92000300509 对应的罗马数字为 MM,CCC,L,IX,MM,CCC,L,IX,MMCCCLIX组合后得到结果为 MMCCCLIX。MMCCCLIX。MMCCCLIX

  • 时间复杂度:O(1)O(1)O(1)
  • 空间复杂度:O(1)O(1)O(1)
class Solution:def intToRoman(self, num: int) -> str:M = ["", "M", "MM", "MMM"] # 1000,2000,3000C = ["", "C", "CC", "CCC", "CD", "D", "DC", "DCC", "DCCC", "CM"] # 100~900X = ["", "X", "XX", "XXX", "XL", "L", "LX", "LXX", "LXXX", "XC"] # 10~90I = ["", "I", "II", "III", "IV", "V", "VI", "VII", "VIII", "IX"] # 1~9return M[num//1000] + C[(num%1000)//100] + X[(num%100)//10] + I[num%10]

3. 贪心算法

在以前还使用现金购物的时候,找零钱的时候一般商家会尽量选择面值大的纸币(硬币)给顾客,这样才会使得给顾客的纸币(硬币)张数最少,让顾客点钱的时候更方便。
贪心法则:尽量使用最大的数来表示,以使表达的数字个数最少。比如对于 1994 这个数,如果我们每次尽量用最大的数来表示,依次选 1000,900,90,41000,900,90,41000900904 会得到正确结果 MCMXCIV。MCMXCIV。MCMXCIV
所以,我们将哈希表按照从大到小的顺序排列,然后遍历哈希表,直到表示完整个输入。

  • 时间复杂度:O(1)O(1)O(1)
  • 空间复杂度:O(1)O(1)O(1)
class Solution:def intToRoman(self, num: int) -> str:dict = {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'}s = ''# 遍历字典的键值for key in dict:if num // key != 0:a = num // keys += a * dict[key]num %= keyreturn s