Given a roman numeral, convert it to an integer.
Input is guaranteed to be within the range from 1 to 3999.
This problem is similar to the previous one. Just keep in mind that we need to consider the letter next to the current one.
C++ Code non-recursive:
/* * func: roman_to_int * goal: convert roman numerial to integer * @param s: input roman numeral string * return: return the int integer */ /* * check every possibility */ int roman_to_int(string &s){ assert(s.length() > 0); int ret = 0; int idx = 0; //Append an unused char to the tail in case of idx+1 s += 'A'; int length = static_cast<int>(s.length()); while(idx < length){ if(s[idx] == 'M'){ ret += 1000; ++idx; }else if(s[idx] == 'C' && s[idx+1] == 'M'){ ret += 900; idx += 2; }else if(s[idx] == 'C' && s[idx+1] == 'D'){ ret += 400; idx += 2; }else if(s[idx] == 'C'){ ret += 100; ++idx; }else if(s[idx] == 'D'){ ret += 500; ++idx; }else if(s[idx] == 'X' && s[idx+1] == 'C'){ ret += 90; idx += 2; }else if(s[idx] == 'X' && s[idx+1] == 'L'){ ret += 40; idx += 2; }else if(s[idx] == 'X'){ ret += 10; ++idx; }else if(s[idx] == 'L'){ ret += 50; ++idx; }else if(s[idx] == 'I' && s[idx+1] == 'X'){ ret += 9; idx += 2; }else if(s[idx] == 'I' && s[idx+1] == 'V'){ ret += 4; idx += 2; }else if(s[idx] == 'V'){ ret += 5; ++idx; }else if(s[idx] == 'I'){ ret += 1; ++idx; }else{ ++idx; } } return ret; }
C++ Code recursive:
int _romanToInt(string s, int index, int result){ if(index == s.size()) return result; if(s[index] == 'M') return result + 1000 + _romanToInt(s, index+1, result); if(s[index] == 'D') return result + 500 + _romanToInt(s, index+1, result); if(s[index] == 'C'){ if(((index + 1) != s.size()) && s[index+1] == 'D') return result + 400 + _romanToInt(s, index+2, result); else if(((index + 1) != s.size()) && s[index+1] == 'M') return result + 900 + _romanToInt(s, index+2, result); else return result + 100 + _romanToInt(s, index+1, result); } if(s[index] == 'L') return result + 50 + _romanToInt(s, index+1, result); if(s[index] == 'X'){ if(((index + 1) != s.size()) && s[index+1] == 'L') return result + 40 + _romanToInt(s, index+2, result); else if(((index + 1) != s.size()) && s[index+1] == 'C') return result + 90 + _romanToInt(s, index+2, result); else return result + 10 + _romanToInt(s, index+1, result); } if(s[index] == 'V') return result + 5 + _romanToInt(s, index+1, result); if(s[index] == 'I'){ if(((index + 1) != s.size()) && s[index+1] == 'V') return result + 4 + _romanToInt(s, index+2, result); else if(((index + 1) != s.size()) && s[index+1] == 'X') return result + 9 + _romanToInt(s, index+2, result); else return result + 1 + _romanToInt(s, index+1, result); } return result; } int romanToInt(string s){ int index = 0; int result = 0; return _romanToInt(s, index, result); }
For the python code, we try to solve it in another way. We can calculate from the end to the start. Thus, for cases like 'IV', we can add 5 first and then subtract 1.
Python Code:
# func: convert a roman numeral to a integer # @param s: input roman numeral string # @return: return integer def roman_to_integer(s): assert s #The dictionary to store the roman-int conversion roman_dict = {'I': 1, 'V': 5, 'X': 10, 'L': 50, 'C': 100, 'D': 500, 'M': 1000} ret = roman_dict[s[-1]] for i in range(2, len(s)+1): if roman_dict[s[1-i]] <= roman_dict[s[-i]]: ret += roman_dict[s[-i]] else: ret -= roman_dict[s[-i]] return ret
I looked at this method online and thought it is very concise. It tries to solve the problem in a reversed order way to avoid consider every two-letter combination separately. However, I compared the running time of this code with mine in C++. This code is a little bit slower (388ms vs 284ms). I think the reason is that it includes comparison in each iteration and more arithmetic calculations since it add one number first and then subtract one. But it is a really good idea.
Reference Link:
1.Roman numerals: http://en.wikipedia.org/wiki/Roman_numerals
2.Roman to Integer - LeetCode: http://discuss.leetcode.com/questions/195/roman-to-integer
No comments:
Post a Comment