LeetCode #13. Roman to Integer プログラミング練習

問題:

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. There are six instances where subtraction is used:

I can be placed before V (5) and X (10) to make 4 and 9.
X can be placed before L (50) and C (100) to make 40 and 90.
C can be placed before D (500) and 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:

Input: "III"
Output: 3
Example 2:

Input: "IV"
Output: 4
Example 3:

Input: "IX"
Output: 9
Example 4:

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

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

難易度: easy
入力: String
目的: 入力されたローマ数字を整数に換えよ
出力: int

♯12問の逆の問題で、ローマ数字を整数に変換する問題です。

ローマ数字:
I 1
V 5
X 10
L 50
C 100
D 500
M 1000
表し方は、大きい数字を中心に、左側はマイナス、右側はプラスです。
例えば
VIは5+1でIVは5-1です。
大きな数字も同様で、
MCは1100で、
CMは900です。

♯12を解けたのなら簡単に解けるはずです。
ただ、入力がStringなので、前回の様にString型Arrayで変換対応数字を捉える事が出来ないので、
私はHashMapを使いました。

注意すべき事: 

  • IVは4ですが、IIVと言う表記はありません。3はIIIだからです。


以下回答です。

class Solution {
    public int romanToInt(String s) {
        HashMap<Character, Integer> map = new HashMap<>();
        map.put('M',1000);
        map.put('D',500);
        map.put('C',100);
        map.put('L',50);
        map.put('X',10);
        map.put('V',5);
        map.put('I',1);
        int res = map.get(s.charAt(0));
        for (int i=1; i<s.length(); i++) {
            if (map.get(s.charAt(i)) > map.get(s.charAt(i-1))) {
                res += map.get(s.charAt(i)) - 2*map.get(s.charAt(i-1));
            }
            else {
                res += map.get(s.charAt(i));
            }
        }
        return res;
    }
}

まず一番最初の文字を取り出し数字に変換します。
次にForに入り、i番目の文字がi-1番目の文字より大きかった時、この時i-1番目の文字はマイナスなので二回引きます。
i番目の文字がi-1番目の文字より小さかった時は普通に変換し足していきます。
これを繰り返せば解けます。

例: 入力 MIV
まず一番最初の文字を変換し足していきます。
res += (M) = 1000
forに入り、先程の文字が表す数字が次の数字より大きいか判断します。
(M) = 1000 > 1 = (I)
なので普通に変換し足します
res += (I) = 1001
次の文字を同じ様に判断し処理します。
(I) = 1 < 5 = (V)
今回は前の文字が表す数字の方が小さいので、この場合Iは-1を表します。
しかし前回の処理でIを1として間違って足してしまったので二回引きます。
res += (V) - 2*(I) = 1001 + 5 - 2 = 1004
すべての文字を読み終わったので出力。

では!