No.012:Integer to Roman

题目:

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。

方法一:

  1. 利用一个二维数组,可以很清晰直观地根据维度来记录罗马字符。
  2. 获取最高位数,根据当前所在位置,对应二维数组的维度。
  3. 获取当前数字,4和9需要特殊处理。
  4. 判断当前数字是否大于等于5,将5对应的罗马字符加入结果字符串。
  5. 计算当前数字除以5的余数,累加1对应的罗马字符。
  6. 入参检查。

方法一的解题代码:

 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     }
method

方法二:

  1. 方法一中使用到了二维数组,可以直观地得到罗马字符,但是二维数组的存储效率是很低的。在Java中,没有二维数组的原生态概念,我们所谓的“二维数组”,其本质是数组的数组,这和C里面不同。Java中使用二维数组,无论是在存储空间还是读取速度方面,都有比较大的劣势,在有等效替代的方法情况下,尽量不要使用二维数组。
  2. 题中的二维数组是2*4的,对于m*n的二维数组,可以使用一维数组代替,下标索引的计算,可以参考m进制的加法原理。

方法二的解题代码:

 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     }
intToRoman

相关链接:

https://leetcode.com/problems/integer-to-roman/

https://github.com/Gerrard-Feng/LeetCode/blob/master/LeetCode/src/com/gerrard/algorithm/medium/Q012.java

PS:如有不正确或提高效率的方法,欢迎留言,谢谢!

原文地址:https://www.cnblogs.com/jing-an-feng-shao/p/5944776.html