整数与罗马数字之间的转换
转换规则
题目来源于Leetcode,整数与罗马数字之间的转换规则大致如下:
字符 数值
I 1
V 5
X 10
L 50
C 100
D 500
M 1000
例如, 罗马数字 2 写做 II ,即为两个并列的 1 。12 写做 XII ,即为 X + II 。 27 写做 XXVII, 即为 XX + V + II 。
通常情况下,罗马数字中小的数字在大的数字的右边。但也存在特例,例如 4 不写做 IIII,而是 IV。数字 1 在数字 5 的左边,所表示的数等于大数 5 减小数 1 得到的数值 4 。同样地,数字 9 表示为 IX。这个特殊的规则只适用于以下六种情况:
I 可以放在 V (5) 和 X (10) 的左边,来表示 4 和 9。
X 可以放在 L (50) 和 C (100) 的左边,来表示 40 和 90。
C 可以放在 D (500) 和 M (1000) 的左边,来表示 400 和 900。
示例:
整数:58 罗马数字:”LVIII”
解释: L = 50, V = 5, III = 3.
整数: 1994 罗马数字: “MCMXCIV”
解释: M = 1000, CM = 900, XC = 90, IV = 4.
转换方案
定义这些特殊的数字对应关系如下:
1 2
| single ={"I":1,"V":5,"X":10,"L":50,"C":100,"D":500,"M":1000} protype={"IV":4,"IX":9,"XL":40,"XC":90,"CD":400,"CM":900}
|
- 罗马数字->整数:
从左到右,将罗马数字拆分成一个个的数组,优先选择拆分成上边的protype中的两位数,如果组合不成两位,便拆分成single中的一位。然后根据对应关系,直接计算出答案。
- 整数->罗马数字:
这个就跟钱币找零的方法是一样的(实在是太简单了),按从大到小进制进行整除,然后选择对应关系就OK。
- 这里只是为了方便理解,把他分成了两个对象,实际操作中,可以合并成一个。
代码实现
- 罗马数字->整数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| def romanToInt(self, s: str) -> int: nums = { "I": 1, "V": 5, "X": 10, "L": 50, "C": 100, "D": 500, "M": 1000, "IV": 4, "IX": 9, "XL": 40, "XC": 90, "CD": 400, "CM": 900 } if(len(s)==1): return nums[s] total = 0 i = 0 while i < len(s): if i + 1 < len(s) and s[i:i+2] in nums: total += nums[s[i:i+2]] i += 2 else: total += nums[s[i]] i += 1
return total
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
| public int romanToInt(String s) { Map<String, Integer> nums = new HashMap<>(); nums.put("I", 1); nums.put("V", 5); nums.put("X", 10); nums.put("L", 50); nums.put("C", 100); nums.put("D", 500); nums.put("M", 1000); nums.put("IV", 4); nums.put("IX", 9); nums.put("XL", 40); nums.put("XC", 90); nums.put("CD", 400); nums.put("CM", 900);
char[] sArray = s.toCharArray(); int total = 0; int i = 0;
while (i < sArray.length) { if (i + 1 < sArray.length && nums.containsKey(sArray[i] + "" + sArray[i + 1])) { total += nums.get(sArray[i] + "" + sArray[i + 1]); i += 2; } else { total += nums.get(sArray[i] + ""); i += 1; } } return total; }
|
- 整数->罗马数字
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| def intToRoman(self, num): od = collections.OrderedDict() od[1000]= "M" od[900]= "CM" od[500]= "D" od[400]= "CD" od[100]= "C" od[90]= "XC" od[50]= "L" od[40]= "XL" od[10]= "X" od[9]= "IX" od[5]= "V" od[4]= "IV" od[1]= "I" res="" for i,v in od.items(): max_num=num//i print(num,i,max_num) res+=od[i]*max_num num -= max_num*i return res
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
| public String intToRoman(int num) { Map<Integer,String> map= new LinkedHashMap<>(); map.put( 1000,"M"); map.put( 900,"CM"); map.put( 500,"D"); map.put( 400,"CD"); map.put( 100,"C"); map.put( 90,"XC"); map.put( 50,"L"); map.put( 40,"XL"); map.put( 10,"X"); map.put( 9,"IX"); map.put( 5,"V"); map.put(4,"IV"); map.put(1,"I");
StringBuffer sb = new StringBuffer(); final int[] arr = {num}; map.forEach((key,value)->{ int max = arr[0]/key; for(int i =0;i<max;i++){ sb.append(value); } arr[0] = arr[0]-max*key; });
return sb.toString(); }
|