题目简述:


Roman numerals are represented by seven different symbols: I, V, X, L, C, D and M.

Symbol Value
I 1
V 5
X 10
L 50
C 100
D 500
M 1000

For example, two is written as II in Roman numeral, just two one’s added together. Twelve is written as, XII, which is simply X + II. The number twenty seven is written as XXVII, which is XX + V + II.

Roman numerals are usually written largest to smallest from left to right. However, the numeral for four is not IIII. Instead, the number four is written as IV. Because the one is before the five we subtract it making four. The same principle applies to the number nine, which is written as IX.


简而言之,从I到M七个字母分别代表着1~1000的七种不同大小。当所给罗马数字的字母顺序为从M到I的顺序排列时,它的值即为其字母所代表的值相加,比如’XXVII’,即表示X+X+V+I+I。当所给罗马数字字符串中有一个字母比这个字母其后的字母所表示的值小时,这两个字母结合起来代表一个数值,其值为(后一个字母的值-前一个字母的值),比如’MCD’,C的值比D小,因此等于M+CD=1000+500-100=1400。

解题思路

其实经过分析过后思路就很明确了,比较所给字符串中当前字母和下一个字母的数值大小,如果当前字母的值比下一个字母的值大,直接相加,反之则后一个字母的值减去当前字母的值,并将这两个字母当作一个整体。

有了思路,就得有解题方法。既然是涉及到前后两个字母进行比较,那么就有两种情况,一种是获取当前字母的值,与后一个字母进行比较;一种是保存前一个字母的值,与当前字母的值进行比较。


当前字母与前一个字母相比较

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
class Solution {
public int romanToInt(String s) {
int[] a = new int[26];
a['I' - 'A'] = 1;
a['V' - 'A'] = 5;
a['X' - 'A'] = 10;
a['L' - 'A'] = 50;
a['C' - 'A'] = 100;
a['D' - 'A'] = 500;
a['M' - 'A'] = 1000;

int sum = 0;
char prev = 'A';
for (char str : s.toCharArray()) {
if(a[str - 'A'] > a[prev - 'A']){
sum = sum - 2*a[prev - 'A'];
}
sum = sum + a[str - 'A'];
prev = str;
}
return sum;
}
}

这种方法foreach中,当前值为str,保存的前一个字母为prev。当当前字母的值大于前一个字母的值时,整体总数sum减去前一个字母的值的两倍(一倍拿来消除之前加过的前一个字母的值,一倍拿来做整体两个字母的减数)。从而得出结果。


当前字母与后一个字母相比较

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
class Solution {
public int romanToInt(String s) {
HashMap<Character, Integer> chara = new HashMap<>();
chara.put('I', 1);
chara.put('V', 5);
chara.put('X', 10);
chara.put('L', 50);
chara.put('C', 100);
chara.put('D', 500);
chara.put('M', 1000);

int sum = 0; //定义总数
for(int i = 0; i < s.length(); i++){
if(i < s.length()-1 && chara.get(s.charAt(i)) < chara.get(s.charAt(i+1))){
sum = sum - chara.get(s.charAt(i));
}else{
sum = sum + chara.get(s.charAt(i));
}
}
return sum;
}
}

使用Map进行存储,当时使用数组也可以,只是为了存储多元化。这种方法要注意charAt的界限,防止越界。当当前的字母的值大于下一个字母的值时,正常相加;反之则总数sum减去当前字母的值。

有一点值得注意的是if的条件中有个i < s.length()-1,即为了防止越界我们作比较只比较到了字符串的倒数第二个字母,最后一个字母的值是直接相加的。因为最后一个字母无需与其后的字母相比较,因此此种方法可行。