LeetCode 12. Integer to Roman 解题报告
题目描述
Given an integer, convert it to a roman numeral.
Input is guaranteed to be within the range from 1 to 3999.
示例
“19”
return “XIX”
限制条件
没有明确给出.
解题思路
我的思路:
之前有一道题是LeetCode 13. Roman to Integer里面有讲到罗马数字的规则,下面我再贴出来一下。
1.基本字母及其代表的数值
I = 1,V = 5,X = 10,L = 50,C = 100,D = 500,M = 1000
2.记数方式
(1)相同的数字连写,所表示的数等于这些数字相加得到的数,如: Ⅲ = 3;
(2)小的数字在大的数字的右边,所表示的数等于这些数字相加得到的数, 如:Ⅷ = 8;Ⅻ = 12;
(3)小的数字,(限于Ⅰ、X 和 C)在大的数字的左边,所表示的数等于大数减小数得到的数,如:Ⅳ = 4;Ⅸ = 9;
知道了上述规则之后,我的想法是对整数不断做减法,因为罗马数字其实就是各个基数的简单组合,比如600 = 500 + 100 = DC,所以从最大的基数开始,如果当前的整数比基数大,那就意味着这个整数的罗马数字表示中包含这个基数对应的字母,因此把该字母添加到结果字符串中,直到整数减至0。
然而这里出现了一个问题,就是罗马数字中表示4,9,40,90,400,900是通过上述规则的第三条表示的,如果直接用减法会导致出现4个连续相同的字母,这是不对的,比如4,用减法得到的结果为IIII。由于特殊的数只有这6个,所以干脆把这6个数也当作基数。假如我们遇到的整数为4,就直接从整数中减去4,并且添加“IV”到结果字符串中,其它5个特殊的数字同样操作。如此我们就能得到正确的结果。
参考思路:
大牛们的思路比我更强势,他们利用了题目里整数不超过3999这一条件,把个位,十位,百位,千位一共34种罗马数字的组合存储到数组中,然后依次取整数的千位,百位,十位,个位上的数字并查数组获取对应的字母,添加到结果字符串中,如此虽然耗费了空间,但是时间上会更快一些。
代码
我的代码
class Solution {
public:
string intToRoman(int num) {
vector<pair<string, int>> baseNumber {
{"I", 1}, {"IV", 4}, {"V", 5}, {"IX", 9},
{"X", 10}, {"XL", 40}, {"L", 50}, {"XC", 90},
{"C", 100}, {"CD", 400}, {"D", 500}, {"CM", 900},
{"M", 1000}
};
int i = 12;
string roman;
while (num > 0) {
if (num >= baseNumber[i].second) {
roman += baseNumber[i].first;
num -= baseNumber[i].second;
} else {
i--;
}
}
return roman;
}
};
参考代码:
class Solution {
public:
string intToRoman(int num) {
char *rLetter[4][10] = {
{"", "I", "II", "III", "IV", "V", "VI", "VII", "VIII", "IX"},
{"", "X", "XX", "XXX", "XL", "L", "LX", "LXX", "LXXX", "XC"},
{"", "C", "CC", "CCC", "CD", "D", "DC", "DCC", "DCCC", "CM"},
{"", "M", "MM", "MMM"}
};
string roman;
roman += rLetter[3][num / 1000 % 10];
roman += rLetter[2][num / 100 % 10];
roman += rLetter[1][num / 10 % 10];
roman += rLetter[0][num % 10];
return roman;
}
};
总结
这道题难度一般,关键是得想到要把特殊的数字跟对应的罗马字母存储起来,当然题目给出了整数范围,所以可以更进一步直接把所有可能的情况都存储起来,想到这一点,这道题就再也没有难度了。
填好今天的坑,明天继续,再忙也坚持每天填一个坑,坚持!加油!