题目链接:Roman to Integer

Given a roman numeral, convert it to an integer.

Input is guaranteed to be within the range from 1 to 3999.

这道题的要求是将罗马数字转化成整数,其中输入数据范围是1到3999。

罗马数字是最早的数字表示方式,比阿拉伯数字早2000多年,起源于罗马。

罗马数字的计数方法:(出自百度百科

罗马字符    I   V   X   L   C   D   M
整数数字    1   5   10  50  100 500 1000
  1. 相同的数字连写,所表示的数等于这些数字相加得到的数,如:III = 3;
  2. 小的数字在大的数字的右边,所表示的数等于这些数字相加得到的数, 如:VIII = 8;XII = 12;
  3. 小的数字,(限于I、X 和C)在大的数字的左边,所表示的数等于大数减小数得到的数,如:IV= 4;IX= 9;
  4. 正常使用时,连写的数字重复不得超过三次。(表盘上的四点钟“IIII”例外)
  5. 在一个数的上面画一条横线,表示这个数扩大1000倍。(本题用不到这点)

有几条须注意掌握:

  1. 基本数字I、X、C中的任何一个,自身连用构成数目,或者放在大数的右边连用构成数目,都不能超过三个;放在大数的左边只能用一个。
  2. 不能把基本数字V、L、D中的任何一个作为小数放在大数的左边采用相减的方法构成数目;放在大数的右边采用相加的方式构成数目,只能使用一个。
  3. V和X左边的小数字只能用I,且只能有1个。
  4. L和C左边的小数字只能用X,且只能有1个。
  5. D和M左边的小数字只能用C,且只能有1个。

看懂了上面的规则后,就可以对输入字符串的每个字符逐个进行判断,重点是方便的将字符映射成为整数,可以采用map,这里采用数组进行映射。只有1种特殊情况,就是当前字符对应的数字小于后面的数字,说明是4或者9,即需要加的是后面的数字减去前面的数字。所以在判断某字符的时候,看一下后面字符是否大于该字符或者记录前面字符大小,都是可以的。

时间复杂度:O(n)

空间复杂度:O(1)

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
class Solution 
{
public:
    int romanToInt(string s) 
    {
        const int N = 7;
        char r[N] = {'I', 'V', 'X', 'L', 'C', 'D', 'M'};
        int n[N] = {1, 5, 10, 50, 100, 500, 1000}, c[26];
        for(int i = 0; i < N; ++ i)
            c[r[i] - 'A'] = n[i];
        
        int sum = 0, l = s.length();
        for(int i = 0; i < l; ++ i)
        {
            if(i + 1 < l && c[s[i + 1] - 'A'] > c[s[i] - 'A'])
            {
                sum += c[s[i + 1] - 'A'] - c[s[i] - 'A'];
                ++ i;
            }
            else
                sum += c[s[i] - 'A'];
        }
        
        return sum;
    }
};