LeetCode之13---Roman to Integer
题目:
Given a roman numeral, convert it to an integer.
Input is guaranteed to be within the range from 1 to 3999.
Input is guaranteed to be within the range from 1 to 3999.
题目大意:
给定一个罗马数字,将其转化为一个整数。转化好的整数的范围在1---3999之间。
思路:
有了上一题的经验,我们可以将待转化的罗马数字和阿拉伯数字的映射创建一个表(这次只创建不同的符号和相减的组合情况,如:IX),然后从字符串的最后一个到第一个开始遍历,遍历一个加一个对应的阿拉伯数字,然后再和前边遍历的合在一起查找是否在表中,如果在则减掉多加的数字。
代码:
class Solution { public: int romanToInt(std::string s) { int result = 0; int pos = s.size() - 1; //建表 std::map<std::string, int> romanNums = { {"I", 1}, {"V", 5} , {"IV", 4}, {"IX", 9}, {"X", 10}, {"L", 50}, {"XL", 40}, {"XC", 90}, {"XC", 90}, {"C", 100}, {"CD", 400}, {"D", 500}, {"CM", 900}, {"M", 1000} }; if (pos < 0) { return 0; } auto pre = romanNums.find(s.substr(pos, 1)); std::map<std::string, int>::iterator tmp; while (pos >= 0) { auto now = romanNums.find(s.substr(pos, 1)); //查找对应的数字 result += now->second; //加到结果上 if ((tmp = romanNums.find(now->first + pre->first)) != romanNums.end()) { //和前一个遍历的合起来是不是一个组合 result = result - (now->second + pre->second - tmp->second); //如果是组合,则删除多加的 } pre = now; --pos; } return result; } };提交后发现发现好耗时啊(100ms左右)。。。。
优化:
将上边思想进行优化,可以发现上边的思想在有组合出现时会出现先加再减的重复过程。所以可以在这里想办法把重复的这个过程减掉。其实不难发现出现组合情况的就是前一个小于后一个数,所以可以将上述思想反其道行之,从前向后扫描,当i的值小于i+1的值时将i的值减掉,否则将i的值加上。
优化后代码:
class Solution { public: int romanToInt(std::string s) { int result = 0; if (s.empty()) { return 0; } std::map<char, int> romanNums = { {'I', 1}, {'V', 5}, {'X', 10}, {'L', 50}, {'C', 100}, {'D', 500}, {'M', 1000} }; for (int i = 0; i < s.size(); ++i) { if (i + 1 < s.size()) { if (romanNums.find(s[i])->second < romanNums.find(s[i + 1])->second) { result -= romanNums.find(s[i])->second; } else { result += romanNums.find(s[i])->second; } } else { result += romanNums.find(s[i])->second; } } return result; } };
运行时间60ms左右。根据上一道题的经验,将map换成int romanNums[89](因为'X'的ASCII码为88)应该可以减少时间。So。。。下边代码就诞生了。
class Solution { public: int romanToInt(std::string s) { int result = 0; if (s.empty()) { return 0; } int romanNums[89]; romanNums['I'] = 1; romanNums['V'] = 5; romanNums['X'] = 10; romanNums['L'] = 50; romanNums['C'] = 100; romanNums['D'] = 500; romanNums['M'] = 1000; for (int i = 0; i < s.size(); ++i) { if (i + 1 < s.size()) { if (romanNums[s[i]] < romanNums[s[i + 1]]) { result -= romanNums[s[i]]; } else { result += romanNums[s[i]]; } } else { result += romanNums[s[i]]; } } return result; } };
最终时间36ms,可是这样的写法总感觉有点像C with class。。。