题目:
Integer to Roman
Given an integer, convert it to a roman numeral.
Input is guaranteed to be within the range from 1 to 3999.
来源:http://oj.leetcode.com/problems/integer-to-roman/
思路:
Background:
首先,学习一下罗马数字,参考罗马数字
罗马数字是最古老的数字表示方式,比阿拉伯数组早2000多年,起源于罗马
罗马数字有如下符号:
基本字符 | I | V | X | L | C | D | M |
对应阿拉伯数字 | 1 | 5 | 10 | 50 | 100 | 500 | 1000 |
计数规则:
- 相同的数字连写,所表示的数等于这些数字相加得到的数,例如:III = 3
- 小的数字在大的数字右边,所表示的数等于这些数字相加得到的数,例如:VIII = 8
- 小的数字,限于(I、X和C)在大的数字左边,所表示的数等于大数减去小数所得的数,例如:IV = 4
- 正常使用时,连续的数字重复不得超过三次
- 在一个数的上面画横线,表示这个数扩大1000倍(本题只考虑3999以内的数,所以用不到这条规则)
其次,罗马数字转阿拉伯数字规则(仅限于3999以内):
最先想到的
用switch处理。不过代码量较大。
后来在查找网络的时候发现
只有4,9是左减,其余的数字都是右加。
所以,构建两个数组,分别是数字和对应的字母。
数字,要把所有的4,9加进来。包括4,9,40,90,400,900.
从前向后遍历罗马数字,如果某个数比前一个数小,则加上该数。反之,减去前一个数的两倍然后加上该数
以及最后网上流行的一个使用vector pair对的方案。
C++ AC代码:
switch-case方案:
class Solution {
public:
string intToRoman(int num) {
if(num <= 0 || num >= 4000)
return NULL;
string roman[] = { "I","V","X","L","C","D","M" };
string RomanString = "";
while(num != 0)
{
int temp = num % 10;
string Rstr = "";
switch(temp)
{
case 1:
Rstr = roman[i];
break;
case 2:
Rstr = roman[i] + roman[i];
break;
case 3:
Rstr = roman[i] + roman[i] + roman[i];
break;
case 4:
Rstr = roman[i] + roman[i+1];
break;
case 5:
Rstr = roman[i+1];
break;
case 6:
Rstr = roman[i+1] + roman[i];
break;
case 7:
Rstr = roman[i+1] + roman[i] + roman[i];
break;
case 8:
Rstr = roman[i+1] + roman[i] + roman[i] + roman[i];
break;
case 9:
Rstr = roman[i] + roman[i+2];
break;
}
RomanString = Rstr + RomanString;
i = i + 2;
num = num / 10;
}
return RomanString;
}
};
运行时间 224ms
方案二:
class Solution {
public:
string intToRoman(int num) {
int integer[] = { 1000,900,500,400,100,90,50,40,10,9,5,4,1 };
string roman[] = { "M","CM","D","CD","C","XC","L","XL","X","IX","V","IV","I" };
if(num <= 0 || num >= 4000)
return NULL;
string RomanString = "";
for (int i = 0; i < sizeof(integer)/sizeof(int); ++i){
while( num >= integer[i] ){
RomanString += roman[i];
num -= integer[i];
}
}
return RomanString;
}
};
运行时间 360ms
使用vector代码:
class Solution {
public:
string intToRoman(int num) {
vector<pair<int, string>> radixes{
{1000,"M"},
{900,"CM"},
{500,"D"},
{400,"CD"},
{100,"C"},
{90,"XC"},
{50,"L"},
{40,"XL"},
{10,"X"},
{9,"IX"},
{5,"V"},
{4,"IV"},
{1,"I"}
};
string roman;
while(num>0)
{
vector<pair<int, string>>::iterator it = radixes.begin();
//这个for循环很机智
for(;num / it -> first == 0;it++)
;
for(int i = 0;i < num / it -> first;i++)
roman += it -> second;
num %= it -> first;
}
return roman;
}
};