LeetCode Python/Java/C++/JS  >  Stack and Queue  >  13. Roman to Integer  >  Solved in Ruby, Python, Java  >  GitHub or Repost

LeetCode link: 13. Roman to Integer, difficulty: Easy.

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, 2 is written as II in Roman numeral, just two ones added together. 12 is written as XII, which is simply X + II. The number 27 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.

Example 1:

Input: s = "III"

Output: 3

Example 2:

Input: s = "IV"

Output: 4

Example 3:

Input: s = "IX"

Output: 9

Example 4:

Input: s = "LVIII"

Output: 58

Explanation: L = 50, V= 5, III = 3.

Example 5:

Input: s = "MCMXCIV"

Output: 1994

Explanation: M = 1000, CM = 900, XC = 90, IV = 4.

Constraints:

  • 1 <= s.length <= 15
  • s contains only the characters ('I', 'V', 'X', 'L', 'C', 'D', 'M').
  • It is guaranteed that s is a valid roman numeral in the range [1, 3999].
Hint 1

Problem is simpler to solve by working the string from back to front and using a map.

Intuition

  • The correspondence between characters and values can be represented with a Map.
  • The intuition is to add the value to result whenever a digit is encountered.
  • But cases like IV may occur, so you need to consider whether to process from left to right or from right to left. Which processing direction do you choose?
    Click to view the answer

    Processing from right to left is more convenient, because once you see that the current character and the previous character form a specific combination, you can handle it directly.

  • How do you deal with cases like IV?
    Click to view the answer

    Just handle it in reverse. In the forward direction you do addition, but now you do subtraction.

Complexity

Time complexity

O(N)

Space complexity

O(1)

Solution in languages: Ruby Python Java

Ruby #

# @param {String} s
# @return {Integer}
def roman_to_int(s)
  symbol_to_value = {
    'I' => 1,
    'V' => 5,
    'X' => 10,
    'L' => 50,
    'C' => 100,
    'D' => 500,
    'M' => 1000,
  }
  result = 0
  previous_char = nil

  (s.size - 1).downto(0).each do |i|
    char = s[i]
    if ('I' == char && ['V', 'X'].include?(previous_char)) || 
       ('X' == char && ['L', 'C'].include?(previous_char)) ||
       ('C' == char && ['D', 'M'].include?(previous_char))
      result -= symbol_to_value[char]
    else
      result += symbol_to_value[char]
    end
    previous_char = char
  end

  result
end

Python #

class Solution:
    def romanToInt(self, s: str) -> int:
        symbol_to_value = {
            'I': 1,
            'V': 5,
            'X': 10,
            'L': 50,
            'C': 100,
            'D': 500,
            'M': 1000,
        }
        result = 0
        previous_char = None

        for i in range(len(s) - 1, -1, -1):
            char = s[i]

            if ('I' == char and previous_char in ['V', 'X']) or \
               ('X' == char and previous_char in ['L', 'C']) or \
               ('C' == char and previous_char in ['D', 'M']):
                result -= symbol_to_value[char]
            else:
                result += symbol_to_value[char]

            previous_char = char

        return result

Java #

class Solution {
    public int romanToInt(String s) {
        Map<Character, Integer> symbolToValue = new HashMap<>();
        symbolToValue.put('I', 1);
        symbolToValue.put('V', 5);
        symbolToValue.put('X', 10);
        symbolToValue.put('L', 50);
        symbolToValue.put('C', 100);
        symbolToValue.put('D', 500);
        symbolToValue.put('M', 1000);

        var result = 0;
        Character previousChar = null;

        for (var i = s.length() - 1; i >= 0; i--) {
            var currentChar = s.charAt(i);

            if (previousChar != null && (
                (currentChar == 'I' && (previousChar == 'V' || previousChar == 'X')) ||
                (currentChar == 'X' && (previousChar == 'L' || previousChar == 'C')) ||
                (currentChar == 'C' && (previousChar == 'D' || previousChar == 'M')))) {
                result -= symbolToValue.get(currentChar);
            } else {
                result += symbolToValue.get(currentChar);
            }

            previousChar = currentChar;
        }

        return result;
    }
}
Solution in languages: Ruby Python Java

Other languages

Welcome to contribute code to LeetCode.to GitHub -> 13. Roman to Integer. Thanks!