题目要求
罗马数字包含以下七种字符: I, V, X, L,C,D 和 M。
字符 | 数值 |
---|---|
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。
给定一个罗马数字,将其转换成整数。输入确保在 1 到 3999 的范围内。
示例
输入:“III” 输出:3
输入:“IV” 输出:4
输入:“IX” 输出:9
输入:“LVIII” 输出:58(L = 50, V= 5, III = 3)
输入:“MCMXCIV” 输出:1994(M = 1000, CM = 900, XC = 90, IV = 4)
Java解题
public int changeRoman(Character character){
switch (character){
case 'I': return 1;
case 'V': return 5;
case 'X': return 10;
case 'L': return 50;
case 'C': return 100;
case 'D': return 500;
case 'M': return 1000;
default: return 0;
}
}
写一个方法,用switch语句将题目表格中的罗马数字与整数进行转化。
- 方法一
public int romanToInt(String s) {
int[] array = new int[s.length()];
int result = changeRoman(s.charAt(s.length() - 1));
for (int i = 0; i < s.length() - 1; i++){
int a = changeRoman(s.charAt(i));
int b = changeRoman(s.charAt(i+1));
if (a < b) a = (-1) * a;
array[i] = a;
}
for (int i = 0; i < array.length; i++){
result += array[i];
}
return result;
}
执行用时:6 ms, 在所有 Java 提交中击败了95.55%的用户
内存消耗:36.2 MB, 在所有 Java 提交中击败了98.07%的用户
解题思路:罗马字符的最后一个数字不管比前一个数字大还是小都会进行加运算,所以将结果先赋值为罗马字符串最后一个数字的整数转化结果。
整数数组存放每一位罗马数字对应的整数结果。
之后,对罗马字符串0~length-1进行遍历,如果第i个数小于第i+1个数,那么说明要用后一个数减去前一个数,也就是后一个数是加运算,前一个数是减运算,将前一个数*(-1)放入整数数组。
最后将数组中的整数依次相加在于result相加,即为结果。
- 方法二
public int romanToInt(String s) {
int result = 0;
for (int i = 0; i < s.length(); i++){
result += changeRoman(s.charAt(i));
if (i != 0){
if ((s.charAt(i) == 'V' || s.charAt(i) == 'X') && s.charAt(i - 1) == 'I') result = result - 1 * 2;
if ((s.charAt(i) == 'L' || s.charAt(i) == 'C') && s.charAt(i - 1) == 'X') result = result - 10 * 2;
if ((s.charAt(i) == 'D' || s.charAt(i) == 'M') && s.charAt(i - 1) == 'C') result = result - 100 * 2;
}
}
return result;
}
执行用时:6 ms, 在所有 Java 提交中击败了95.55%的用户
内存消耗:36.7 MB, 在所有 Java 提交中击败了95.49%的用户
解题思路:遍历罗马数字的每一位,将其按照加运算进行计算,然后根据题目给出的四种特殊情况进行判断,如果如何情况说明需要进行减运算,而我们已经进行了加运算,所以把我们自己加的一次减去,再把应该减的一次减去,一共做两次减运算,最终得出结果。
- 方法三
public int romanToInt(String s) {
if (s.length() == 1) return changeRoman(s.charAt(0));
if (s.length() == 2){
if (changeRoman(s.charAt(0)) < changeRoman(s.charAt(1))) return changeRoman(s.charAt(1)) - changeRoman(s.charAt(0));
else return changeRoman(s.charAt(0)) + changeRoman(s.charAt(1));
}
if (changeRoman(s.charAt(s.length() - 1)) > changeRoman(s.charAt(s.length() - 2)))
return changeRoman(s.charAt(s.length() - 1)) - changeRoman(s.charAt(s.length() - 2)) + romanToInt(s.substring(0, s.length() - 2));
else
return changeRoman(s.charAt(s.length() - 1)) + romanToInt(s.substring(0, s.length() - 1));
}
执行用时:7 ms, 在所有 Java 提交中击败了93.10%的用户
内存消耗:39.9 MB, 在所有 Java 提交中击败了73.78%的用户
解题思路:利用递归的思想解题。方法出口,如果字符串长度为1,直接返回其所对应的罗马数字;如果字符串长度为2,根据前小后大后减前,前大后小两相加的方法计算结果;其他情况,如果最后一位大于倒数第二位,将此两位计算出结果,然后将除此两位的字符串继续递归计算结果,否则直接加最后一位就将除最后一位外的字符串递归计算。