题目
罗马数字包含以下七种字符:
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。这个特殊的规则只适用以下6种情况:
- I可以放在V(5)和X(10)的左边,来表示4和9.
- X可以放在L(50)和C(100)的左边,来表示40和90.
- C可以放在D(500)和M(1000)的左边,来表示400和900。
给定一个罗马数字,将其转化成整数。输入确保在1到3999的范围内。
示例1:
输入:“III”
输出:“3”
实例2:
输入:“IV”
输出:“4”
实例3:
输入:“IX”
输出:“9”
示例 4:
输入: “LVIII”
输出: 58
解释: L = 50, V= 5, III = 3.
示例 5:
输入: “MCMXCIV”
输出: 1994
解释: M = 1000, CM = 900, XC = >90, IV = 4.
思路
罗马数字除了6种特殊情况外,总是左边数字大于等于右边数字。所以从左到右遍历数字字符串,若左边大于右边,加上当前对应的值,否则减去当前对应的值,需要注意的是,最后一个值要记得加上。
public int romanToInt(String s) throws Exception{
int index = 0;
Character c,n;
int result = 0;
while(index < s.length()-1){
c = s.charAt(index++);
n = s.charAt(index);
if(judgeValue(c) < judgeValue(n)){
//左边数字小于右边数字,减去对应值
result -= judgeValue(c);
}else {
//左边数字大于右边数字,加上对应值
result += judgeValue(c);
}
}
result += judgeValue(s.charAt(index)); //加上最后一个数字
if(result > 3999){ //数值溢出抛异常
throw new Exception("数值必须在1-3999之间");
}
return result;
}
/**
* 对应单个罗马数字转化阿拉伯数字的值
*/
private int judgeValue(Character c) throws Exception {
switch (c){
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:throw new Exception("WrongRomanNumber"); //非法罗马数字抛异常
}
}
我用了一个switch映射了值的6种情况,超过这6种字符就会抛异常,根据题意,当值溢出(要求1-3999)也会抛异常。然后leedcode上我抛异常的代码总是编译不通过。。。。
改正这样通过了编译。
public int romanToInt(String s) {
int index = 0;
Character c,n;
int result = 0;
while(index < s.length()-1){
c = s.charAt(index ++ );
n = s.charAt(index);
if(judgeValue(c) < judgeValue(n)){
result -= judgeValue(c);
}else {
result += judgeValue(c);
}
}
result += judgeValue(s.charAt(index));
return result;
}
private int judgeValue(Character c) {
switch (c){
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;
}
return 0;
}