leetcode 12.整数转罗马数字
题目描述
罗马数字包含以下七种字符: I
, V
, X
, L
,C
,D
和 M
。
字符 数值
I 1
V 5
X 10
L 50
C 100
D 500
M 1000
例如, 罗马数字 2 写做 II ,即为两个并列的 1。12 写做 XII ,即为 X + II 。 27 写做 XXVII, 即为 XX + V + II 。
通常情况下,罗马数字中小的数字在大的数字的右边。但也存在特例,例如 4 不写做 IIII,而是 IV。数字 1 在数字 5 的左边,所表示的数等于大数 5 减小数 1 得到的数值 4 。同样地,数字 9 表示为 IX。这个特殊的规则只适用于以下六种情况:
- I 可以放在 V (5) 和 X (10) 的左边,来表示 4 和 9。
- X 可以放在 L (50) 和 C (100) 的左边,来表示 40 和 90。
- C 可以放在 D (500) 和 M (1000) 的左边,来表示 400 和 900。
给定一个整数,将其转为罗马数字。输入确保在 1 到 3999 的范围内。
示例 1:
输入: 3
输出: "III"
示例 2:
输入: 4
输出: "IV"
示例 3:
输入: 9
输出: "IX"
示例 4:
输入: 58
输出: "LVIII"
解释: L = 50, V = 5, III = 3.
示例 5:
输入: 1994
输出: "MCMXCIV"
解释: M = 1000, CM = 900, XC = 90, IV = 4.
解题思路
哈希表对应
建立一个哈希表,存放数字对应的罗马字符,对应数字转罗马字符而言,举个例子:298 = 2 * 100 + 1 * 90 + 1 * 5 + 3 * 1
即如果我们可以知道一个num中,他每个罗马单元对应的个数,就可以很方便的说出罗马数字, 298 = “C” + “C” + “XC” + “V” + “I” + “I” + “I”。即可以采用对每个罗马数字取整,计算该罗马数字的数量,就可以转换成整体的罗马数字
class Solution {
public:
string intToRoman(int num) {
string res = "";
if((num<=0) || (num>3999)){
return res;
}
unordered_map<int, string> romanMap = {{1,"I"},{4,"IV"},{5,"V"},{9,"IX"},{10,"X"},{40,"XL"},{50,"L"},{90,"XC"},{100,"C"},{400,"CD"},{500,"D"},{900,"CM"},{1000,"M"}};
unordered_map<int, int> numMap = {{1,1},{2,4},{3,5},{4,9},{5,10},{6,40},{7,50},{8,90},{9,100},{10,400},{11,500},{12,900},{13,1000}};
while(num){
for(int i=13; i>0;i--){
int times = num/numMap[i];
while(times){
res += romanMap[numMap[i]];
times--;
}
num %= numMap[i];
}
}
return res;
}
};
贪心算法
每种罗马字符都有对应的数值,把一个数字转换成罗马数字,可以理解为把数字拆分,由指定的几个数字相加得到目标结果。采用贪心算法的思想,即每次尽可能多的取最大的数字,知道num等于零。
class Solution {
public:
string intToRoman(int num) {
vector<int> romanValue = {1000, 900, 500, 400, 100, 90, 50, 40, 10, 9, 5, 4, 1};
vector<string> roman = {"M","CM", "D", "CD", "C", "XC", "L", "XL", "X", "IX", "V", "IV", "I"};
string res = "";
for(int i=0; i<13; i++){
while(num >= romanValue[i]){
res += roman[i];
num -= romanValue[i];
}
}
return res;
}
};
欢迎大家关注我的个人公众号,同样的也是和该博客账号一样,专注分享技术问题,我们一起学习进步