DEV Community

Takahiro Kudo
Takahiro Kudo

Posted on

LeetCode "13. Roman to Integer"

Umm...
How to remove a lot ofpos += 1 and pos < len_str

13. Roman to Integer

class Solution:
    def romanToInt(self, s: str) -> int:

        if not s:
            return 0

        pos = 0
        len_str = len(s)
        numOfDigits = 0
        symbols = ['dummy', ('I', 'V', 'X'), ('X', 'L', 'C'), ('C', 'D', 'M'), ('M')]
        s = s[::-1]
        value = 0

        while pos < len_str:
            num = 0
            numOfDigits += 1

            # ex. I ... III, VI ... VIII
            if s[pos] == symbols[numOfDigits][0]:      
                num = 1
                pos += 1
                while pos < len_str and s[pos] == symbols[numOfDigits][0]:
                    num += 1
                    pos += 1
                if pos < len_str and s[pos] == symbols[numOfDigits][1]:
                    num += 5
                    pos += 1

            # ex. V, IV
            elif s[pos] == symbols[numOfDigits][1]:
                num = 5
                pos += 1
                if pos < len_str and s[pos] == symbols[numOfDigits][0]:
                    num -= 1
                    pos += 1

            # ex. IX, XC, M
            elif s[pos] == symbols[numOfDigits][2]:
                num = 10
                pos += 1
                if pos < len_str and s[pos] == symbols[numOfDigits][0]:
                    num -= 1
                    pos += 1

            value += num * (10 ** (numOfDigits - 1))

        return value
Enter fullscreen mode Exit fullscreen mode

Top comments (4)

Collapse
 
orenovadia profile image
orenovadia

Besides pos += 1 appearing multiple times in the code, I think there is a bigger problem with s[pos] == symbols[numOfDigits][X]: it makes it difficult to understand what number each roman character is mapped to. Since each roman character is mapped to a decimal number, it makes sense putting them in a dict like so:

ROMAN_TO_DECIMAL = {'I': 1, 'V': 5 ...}

This makes things easy. Let's assume for a moment that we have a roman number without reverse-order subtractions (e.g: without IV, IX).

Than you could simply write:

number = 0
for roman in s:
   number += ROMAN_TO_DECIMAL[roman]
return number

This is very neat. And can even be written in one line: sum(ROMAN_TO_DECIMAL[c] for c in s)

How to add the reverse-order subtractions now? Consider and try to implement this pseudo-code:

for roman in s:
   value = ROMAN_TO_DECIMAL[roman]
   if the next roman character is larger than the current:
      # e.g: this character is the 'I' in 'IV', so it should be subtracted from the result
      number -= value
   else:
      number += value
Collapse
 
takakd profile image
Takahiro Kudo

Wow! Thank you for the detailed explanation and code example!😍

I implemented:

ROMAN_TO_DECIMAL = {'I': 1, 'V':5, 'X':10, 'L':50, 'C':100, 'D': 500, 'M':1000}

len_s = len(s)
number = 0
for i in range(len_s - 1):
    value = ROMAN_TO_DECIMAL[s[i]]
    if ROMAN_TO_DECIMAL[s[i]] < ROMAN_TO_DECIMAL[s[i + 1]]:
        number -= value
    else:
        number += value

# last
number += ROMAN_TO_DECIMAL[s[len_s - 1]]
return number

I could not come up with the idea of ROMAN_TO_DECIMAL.😭

When thinking about this problem, did you first think about ROMAN_TO_DECIMAL and then the logic?
Or is the logic first?

If it's ok with you, could you tell me about your thought process?

Collapse
 
orenovadia profile image
orenovadia

I am sorry to disappoint you but I don't really know how I came up with this or in what order. I have solved this question a while ago.

ROMAN_TO_DECIMAL makes sense because for each roman numeral there is one corresponding number. There is a one to one mapping between them, and dict is python's map.

I think that the bottom line is experience. The more questions you solve on leetcode, see how other people's solutions look like, you develop more intuition as to what are the data-structures and algorithms suitable for each problem.

Also, you might find these books helpful, depends on what your goals are, and how much spare time you have:

  1. Cracking the Coding Interview
  2. Elements of Programming Interviews in Python
Thread Thread
 
takakd profile image
Takahiro Kudo

Thank you for your helpful reply.

I thought that the key solved the problem is awareness of "each roman numeral there is one corresponding number".
I will continue to solve problems and gain experiences, with other people's solutions.

And thanks for introducing books!😍