Description
Given an integer, convert it to a roman numeral.
Input is guaranteed to be within the range from 1 to 3999.
Input: 1
Output: "I"
Solution
跟另外一道题类似(Roman to Integer - LeetCode)
链接里面的题目我在上一周的博客里面已经提到了()
首先我们要知道罗马数字每个数字对应的阿拉伯数字大小,如下表所示
罗马数字 | 阿拉伯数字 |
---|---|
I | 1 |
V | 5 |
X | 10 |
L | 50 |
C | 100 |
D | 500 |
M | 1000 |
首先想到的方法把每一个位数上面的数字取出来,然后按照千、百、十、个的顺序分解出每一个位数上面的数字。
然后按照不同的对应关系来完成对照。
拿个位上的数字举例子:
阿拉伯数字(num) | 罗马数字 |
---|---|
1~3 | num * I (num个“I”组成的字符串) |
4 | IV |
5~8 | V + num * I |
9 | IX |
其他的位置同理,改变的只是对应的字母而已,所以一开始我写出了以下的代码:
Source Code
submission I
class Solution {
public:
string intToRoman(int num) {
int thousand = num / 1000;
num = num % 1000;
int hundred = num / 100;
num = num % 100;
int tens = num / 10;
int ones = num % 10;
return getThousandRoman(thousand) +
getHundredRoman(hundred) +
getTensRoman(tens) +
getOnesRoman(ones);
}
string getThousandRoman(int num) // 千位数对应的数字
{
if (num == 0)
{
return "";
}
else if (num == 3)
{
return "MMM";
}
else if (num == 2)
{
return "MM";
}
else if (num == 1)
{
return "M";
}
else
{
return "";
}
}
string getHundredRoman(int num) // 百位数对应的数字
{
if (num == 0)
{
return "";
}
if (num == 9)
{
return "CM";
}
else if (num >= 5)
{
return "D" + getDuplicateRoman(num - 5, "C");
}
else if (num == 4)
{
return "CD";
}
else
{
return getDuplicateRoman(num, "C");
}
}
string getTensRoman(int num) // 十位数对应的数字
{
if (num == 0)
{
return "";
}
if (num == 9)
{
return "XC";
}
else if (num >= 5)
{
return "L" + getDuplicateRoman(num - 5, "X");
}
else if (num == 4)
{
return "XL";
}
else
{
return getDuplicateRoman(num, "X");
}
}
string getOnesRoman(int num) // 个位数对应的数字
{
if (num == 0)
{
return "";
}
if (num == 9)
{
return "IX";
}
else if (num >= 5)
{
return "V" + getDuplicateRoman(num - 5, "I");
}
else if (num == 4)
{
return "IV";
}
else
{
return getDuplicateRoman(num, "I");
}
}
string getDuplicateRoman(int num, string s) // 获取重复的字符
{
string ret = "";
for (int i = 0 ; i < num ; i++)
{
ret += s;
}
return ret;
}
};
Thinking
在完成上述代码之后我发现了代码长度偏长,我的函数中有很多重复的部分,唯一不同的是对应的字母,如果把这些字母也变成参数放进函数里面,就有了以下比较简短的代码:
submission II
class Solution {
public:
string intToRoman(int num) {
int thousand = num / 1000;
num = num % 1000;
int hundred = num / 100;
num = num % 100;
int tens = num / 10;
int ones = num % 10;
return getAnyRoman(thousand, "", "", "M") // 千位
+ getAnyRoman(hundred, "M", "D", "C") // 百位
+ getAnyRoman(tens, "C", "L", "X") // 十位
+ getAnyRoman(ones, "X", "V", "I"); // 百位
}
/***
* num - 0~9
* ten - 十倍表示的字母(如个位对应"X")
* five - 五倍表示的字母(如个位对应"V")
* ten - 一倍表示的字母(如个位对应"I")
*/
string getAnyRoman(int num, string ten, string five, string one)
{
if (num == 0)
{
return "";
}
if (num == 9)
{
return one + ten;
}
else if (num >= 5)
{
return five + getDuplicateRoman(num - 5, one);
}
else if (num == 4)
{
return one + five;
}
else
{
return getDuplicateRoman(num, one);
}
}
string getDuplicateRoman(int num, string s) // 获取重复的字符
{
string ret = "";
for (int i = 0 ; i < num ; i++)
{
ret += s;
}
return ret;
}
};
Better Solution
参考别人的代码(Integer to Roman- LeetCode):
public static String intToRoman(int num) {
String M[] = {"", "M", "MM", "MMM"};
String C[] = {"", "C", "CC", "CCC", "CD", "D", "DC", "DCC", "DCCC", "CM"};
String X[] = {"", "X", "XX", "XXX", "XL", "L", "LX", "LXX", "LXXX", "XC"};
String I[] = {"", "I", "II", "III", "IV", "V", "VI", "VII", "VIII", "IX"};
return M[num/1000] + C[(num%1000)/100] + X[(num%100)/10] + I[num%10];
}
这位大神写的代码十分简短,但是思路是和我的一样的,不过这样子简短而又清晰的代码的确令人佩服!