GuilinDev

Lc0013

05 August 2008

13 - Roman to Integer

原题概述

Roman numerals are represented by seven different symbols:

1
I
,
1
V
,
1
X
,
1
L
,
1
C
,
1
D
and
1
M
.

1
2
3
4
5
6
7
8
Symbol       Value
I             1
V             5
X             10
L             50
C             100
D             500
M             1000

For example, two is written as

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

Roman numerals are usually written largest to smallest from left to right. However, the numeral for four is not

1
IIII
. Instead, the number four is written as
1
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
1
IX
. There are six instances where subtraction is used:

  • 1
    
    I
    
    can be placed before
    1
    
    V
    
    (5) and
    1
    
    X
    
    (10) to make 4 and 9.
  • 1
    
    X
    
    can be placed before
    1
    
    L
    
    (50) and
    1
    
    C
    
    (100) to make 40 and 90.
  • 1
    
    C
    
    can be placed before
    1
    
    D
    
    (500) and
    1
    
    M
    
    (1000) to make 400 and 900.

Given a roman numeral, convert it to an integer. Input is guaranteed to be within the range from 1 to 3999.

Example 1:

1
2
Input: "III"
Output: 3

Example 2:

1
2
Input: "IV"
Output: 4

Example 3:

1
2
Input: "IX"
Output: 9

Example 4:

1
2
3
Input: "LVIII"
Output: 58
Explanation: C = 100, L = 50, XXX = 30 and III = 3.

Example 5:

1
2
3
Input: "MCMXCIV"
Output: 1994
Explanation: M = 1000, CM = 900, XC = 90 and IV = 4.

题意和分析

罗马数字转换为数字,参考Grandyang的解释

1、相同的数字连写,所表示的数等于这些数字相加得到的数,如:Ⅲ = 3;

2、小的数字在大的数字的右边,所表示的数等于这些数字相加得到的数, 如:Ⅷ = 8;Ⅻ = 12;

3、小的数字,(限于Ⅰ、X 和C)在大的数字的左边,所表示的数等于大数减小数得到的数,如:Ⅳ= 4;Ⅸ= 9;

4、正常使用时,连写的数字重复不得超过三次。(表盘上的四点钟“IIII”例外)

5、在一个数的上面画一条横线,表示这个数扩大1000倍。

有几条须注意掌握:

1、基本数字Ⅰ、X 、C 中的任何一个,自身连用构成数目,或者放在大数的右边连用构成数目,都不能超过三个;放在大数的左边只能用一个。

2、不能把基本数字V 、L 、D 中的任何一个作为小数放在大数的左边采用相减的方法构成数目;放在大数的右边采用相加的方式构成数目,只能使用一个。

3、V 和X 左边的小数字只能用Ⅰ。

4、L 和C 左边的小数字只能用X。

5、D 和M 左边的小数字只能用C。 而这道题好就好在没有让我们来验证输入字符串是不是罗马数字,这样省掉不少功夫。我们需要用到map数据结构,来将罗马数字的字母转化为对应的整数值,因为输入的一定是罗马数字,那么我们只要考虑两种情况即可:第一,如果当前数字是最后一个数字,或者之后的数字比它小的话,则加上当前数字第二,其他情况则减去这个数字.

每次跟后面的数字比较,如果小于等于后面的数字,我们先减去之前加上的数字,如果大于的后面的数字,直接加上当前的数,最后一个数后面没有数了,不会被循环到,直接加上。

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
class Solution {
    public int romanToInt(String s) {
        int nums[] = new int[s.length()];//创建一个s包含的字符的长度的数组
        //给新创建的数组每个位置赋值为相对应的值,方便查找
        for (int i = 0; i < s.length(); i++) {
            switch (s.charAt(i)) {
                case 'M':
                    nums[i] = 1000;
                    break;
                case 'D':
                    nums[i] = 500;
                    break;
                case 'C':
                    nums[i] = 100;
                    break;
                case 'L':
                    nums[i] = 50;
                    break;
                case 'X':
                    nums[i] = 10;
                    break;
                case 'V':
                    nums[i] = 5;
                    break;
                case 'I':
                    nums[i] = 1;
                    break;
            }
        }

        int result = 0;
        for(int i = 0; i < nums.length - 1; i++){
            if(nums[i] < nums[i + 1]) // 当前位置为IV IX这样的情况
                result -= nums[i];
            else  // 当前位置为VI XI这样的情况,或者相等
                result += nums[i];
        }
        return result + nums[nums.length - 1]; //最后一位单独加上
    }
}