题目:
Given an integer, convert it to a roman numeral.
Input is guaranteed to be within the range from 1 to 3999.
官方难度:
Medium
翻译:
给定一个范围在1-3999内的整数,将其转化成罗马数字。
补充资料:
罗马数字规则:
- 需要用到的罗马数字共有7个,即I(1)、V(5)、X(10)、L(50)、C(100)、D(500)和M(1000)。罗马数字中没有0。
- 一个罗马数字最多重复3次。
- 右加左减:
在较大的罗马数字的右边记上较小的罗马数字,表示大数字加小数字。
在较大的罗马数字的左边记上较小的罗马数字,表示大数字减小数字。 - 左减的数字有限制,仅限于I、X、C,且放在大数的左边只能用一个。
(*) V 和 X 左边的小数字只能用I。
(*) L 和 C 左边的小数字只能用X。
(*) D 和 M 左 边的小数字只能用C。
方法一:
- 利用一个二维数组,可以很清晰直观地根据维度来记录罗马字符。
- 获取最高位数,根据当前所在位置,对应二维数组的维度。
- 获取当前数字,4和9需要特殊处理。
- 判断当前数字是否大于等于5,将5对应的罗马字符加入结果字符串。
- 计算当前数字除以5的余数,累加1对应的罗马字符。
- 入参检查。
方法一的解题代码:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 // 使用二维数组,存储罗马字符集 2 private static String method(int num) { 3 StringBuffer result = new StringBuffer(); 4 // 罗马字符集 5 char[][] roman = new char[][] { { 'I', 'V' }, { 'X', 'L' }, { 'C', 'D' }, { 'M' } }; 6 // 确定最高位数 7 int length = String.valueOf(num).length(); 8 while (length-- > 0) { 9 // 罗马数字从左往右是最高位的 10 int current = (int) ((num / Math.pow(10, length)) % 10); 11 // 4、9特殊处理 12 if (current == 4) { 13 result.append("" + roman[length][0] + roman[length][1]); 14 } else if (current == 9) { 15 result.append("" + roman[length][0] + roman[length + 1][0]); 16 } else { 17 // 大于等于5处理 18 if (current / 5 == 1) { 19 result.append(roman[length][1]); 20 } 21 // 加1 22 for (int i = 0; i < current % 5; i++) { 23 result.append(roman[length][0]); 24 } 25 } 26 } 27 return result.toString(); 28 }
方法二:
- 方法一中使用到了二维数组,可以直观地得到罗马字符,但是二维数组的存储效率是很低的。在Java中,没有二维数组的原生态概念,我们所谓的“二维数组”,其本质是数组的数组,这和C里面不同。Java中使用二维数组,无论是在存储空间还是读取速度方面,都有比较大的劣势,在有等效替代的方法情况下,尽量不要使用二维数组。
- 题中的二维数组是2*4的,对于m*n的二维数组,可以使用一维数组代替,下标索引的计算,可以参考m进制的加法原理。
方法二的解题代码:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 public static String intToRoman(int num) { 2 if (num > 3999 || num < 1) { 3 throw new IllegalArgumentException("Input error"); 4 } 5 StringBuffer result = new StringBuffer(); 6 // 确定最高位数 7 int length = String.valueOf(num).length(); 8 while (length-- > 0) { 9 // 罗马数字从左往右是最高位的 10 int current = (int) ((num / Math.pow(10, length)) % 10); 11 // 4、9特殊处理 12 if (current == 4) { 13 result.append("" + romanDict(length, 0) + romanDict(length, 1)); 14 } else if (current == 9) { 15 result.append("" + romanDict(length, 0) + romanDict(length + 1, 0)); 16 } else { 17 // 大于等于5处理 18 if (current / 5 == 1) { 19 result.append(romanDict(length, 1)); 20 } 21 // 加1 22 for (int i = 0; i < current % 5; i++) { 23 result.append(romanDict(length, 0)); 24 } 25 } 26 } 27 return result.toString(); 28 } 29 30 // 罗马数字字典 31 private static char romanDict(int x, int y) { 32 char[] roman = new char[] { 'I', 'V', 'X', 'L', 'C', 'D', 'M' }; 33 return roman[x * 2 + y]; 34 }
相关链接:
https://leetcode.com/problems/integer-to-roman/
PS:如有不正确或提高效率的方法,欢迎留言,谢谢!