###### tags: `leetcode` # 13. Roman to Integer ## My 1st idea ### Use dictionary ref = https://en.wikibooks.org/wiki/A-level_Computing/AQA/Paper_1/Fundamentals_of_data_structures/Dictionaries ### try - fail ```python= def function(s): myDict = {'I':1, 'V': 5, 'X': 10,'L': 50, 'C': 100,'D': 500,'M': 1000} cur = 0 # current ct = 0 # counter sum = 0 # Use a style of not changing the input data while ct <= len(s): if myDict(s[len(s) - ct]) <= cur: sum += myDict(s[len(s) - ct]) else: sum -= myDict(s[len(s) - ct]) curr = 0 ct += 1 return sum ``` :::danger s[len(s) - ct] index out of range ::: ### try - fail ```python= class Solution: def romanToInt(self, s: str) -> int: myDict = {'I':1, 'V': 5, 'X': 10,'L': 50, 'C': 100,'D': 500,'M': 1000} cur = 0 # current ct = 0 # counter sum = 0 # Use a style of not changing the input data while len(s) - 1 - ct >= 0: if myDict(s[len(s) - 1 - ct]) <= cur: sum += myDict(s[len(s) - 1 - ct]) else: sum -= myDict(s[len(s) - 1 - ct]) curr = 0 ct =+ 1 return sum ``` :::danger TypeError: 'dict' object is not callable ::: ### try - fail ```python= class Solution: def romanToInt(self, s: str) -> int: myDict = {'I':1, 'V': 5, 'X': 10,'L': 50, 'C': 100,'D': 500,'M': 1000} cur = 0 # current ct = 0 # counter sum = 0 # Use a style of not changing the input data while len(s) - 1 - ct >= 0: if myDict[s[len(s) - 1 - ct]] <= cur: sum += myDict[s[len(s) - 1 - ct]] else: sum -= myDict[s[len(s) - 1 - ct]] curr = 0 ct =+ 1 return sum ``` :::danger Time Limit Exceeded ::: :::warning ct =+ 1 ct += 1 ::: ### try - fail ```python= class Solution: def romanToInt(self, s: str) -> int: myDict = {'I':1, 'V': 5, 'X': 10,'L': 50, 'C': 100,'D': 500,'M': 1000} cur = 0 # current ct = 0 # counter sum = 0 # Use a style of not changing the input data while len(s) - 1 - ct >= 0: if myDict[s[len(s) - 1 - ct]] <= cur: sum += myDict[s[len(s) - 1 - ct]] else: sum -= myDict[s[len(s) - 1 - ct]] curr = 0 ct += 1 return sum ``` :::danger Wrong Answer Runtime: 60 ms Your input "III" Output -3 Expected 3 ::: ### try - success ```python= class Solution: def romanToInt(self, s: str) -> int: myDict = {'I':1, 'V': 5, 'X': 10,'L': 50, 'C': 100,'D': 500,'M': 1000} cur = 0 # current ct = 0 # counter sum = 0 # Use a style of not changing the input data while len(s) - 1 - ct >= 0: if myDict[s[len(s) - 1 - ct]] >= cur: cur = myDict[s[len(s) - 1 - ct]] sum += cur else: sum -= myDict[s[len(s) - 1 - ct]] curr = 0 ct += 1 return sum ``` :::success Accepted Runtime: 60 ms Your input "III" Output 3 Expected 3 ::: :::info Success Details Runtime: 52 ms, faster than 80.23% of Python3 online submissions for Roman to Integer. Memory Usage: 14 MB, less than 5.38% of Python3 online submissions for Roman to Integer. ::: ## another person's I didn't realized that there are only 6 cases of subtraction. ```java= public int romanToInt(String s) { int sum=0; if(s.indexOf("IV")!=-1){sum-=2;} if(s.indexOf("IX")!=-1){sum-=2;} if(s.indexOf("XL")!=-1){sum-=20;} if(s.indexOf("XC")!=-1){sum-=20;} if(s.indexOf("CD")!=-1){sum-=200;} if(s.indexOf("CM")!=-1){sum-=200;} char c[]=s.toCharArray(); int count=0; for(;count<=s.length()-1;count++){ if(c[count]=='M') sum+=1000; if(c[count]=='D') sum+=500; if(c[count]=='C') sum+=100; if(c[count]=='L') sum+=50; if(c[count]=='X') sum+=10; if(c[count]=='V') sum+=5; if(c[count]=='I') sum+=1; } return sum; } ``` ## another person's Unordered_map, ref = https://www.geeksforgeeks.org/unordered_map-in-cpp-stl/ It is implemented by hash table. The same way as mine. Starting from `int sum = T[s.back()];`. Not use `current`. If using `T[s[i]] < T[s[i + 1]]`, at the tail end of the string, the last element will have to compare with something outside the string. So, this person's method is really educational. ```cpp= int romanToInt(string s) { unordered_map<char, int> T = { { 'I' , 1 }, { 'V' , 5 }, { 'X' , 10 }, { 'L' , 50 }, { 'C' , 100 }, { 'D' , 500 }, { 'M' , 1000 } }; int sum = T[s.back()]; for (int i = s.length() - 2; i >= 0; --i) { if (T[s[i]] < T[s[i + 1]]) { sum -= T[s[i]]; } else { sum += T[s[i]]; } } return sum; } ``` ## another person's Why its index will not go out of range?? I mean `if roman[s[i]] < roman[s[i+1]]:`. Oh!Oh!Oh! I now understand. And it has `return z + roman[s[-1]]`, which is really smart!!! Since the last Roman Character is always positive. ```python= class Solution: # @param {string} s # @return {integer} def romanToInt(self, s): roman = {'M': 1000,'D': 500 ,'C': 100,'L': 50,'X': 10,'V': 5,'I': 1} z = 0 for i in range(0, len(s) - 1): if roman[s[i]] < roman[s[i+1]]: z -= roman[s[i]] else: z += roman[s[i]] return z + roman[s[-1]] ``` ## another person's I like `for i in s[::-1]:`. Use it, and I will never have mistakes on reversed for-loop. ```python= def romanToInt(self, s): """ :type s: str :rtype: int """ _dict = {'I':1,'V':5,'X':10,'L':50,'C':100,'D':500,'M':1000} prev = 0 sum = 0 for i in s[::-1]: curr = _dict[i] if prev > curr: sum -= curr else: sum += curr prev = curr return sum ``` ## another person's Easy to track what is the Roman character now. ```python= d = {'M':1000, 'D':500, 'C':100, 'L':50, 'X':10, 'V':5, 'I':1} def romanToInt(self, s): res, p = 0, 'I' for c in s[::-1]: res, p = res - d[c] if d[c] < d[p] else res + d[c], c return res ```