一【题目类别】
- 字符串
二【题目难度】
- 中等
三【题目编号】
- 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.
六【题目提示】
- 1 <= num <= 3999
七【解题思路】
- 哈希表+贪心的思路,建立一共题目提供的十三个数字和罗马字母的对应关系,遍历所有数组,遇到一个num大于等于key的,说明可以拼接一个value,这里就是贪心的思想,如果还有(倍数关系),继续拼接,然后继续for循环,这里有个细节,一定要从大到小排序,因为乱序的话拼接出错,因为我们要找到最接近num的key,也就是整除的最大值,另外如果用C语言编写注意因为LeetCode的gcc版本问题,对数组memset初始化以避免缓存越界
八【时间频度】
- 时间复杂度:时间复杂度为常数级别 O ( 1 ) O(1) O(1),因为一共只需遍历 13 13 13位
九【代码实现】
- Java语言版
package String;
public class p12_IntegerToRoman {
public static void main(String[] args) {
int num = 1994;
System.out.println("第一种方法");
String resI = intToRomanI(num);
System.out.println("resI = " + resI);
System.out.println("第二种方法");
String resII = intToRomanII(num);
System.out.println("resII = " + resII);
}
public static String intToRomanI(int num) {
// 结果数组
String res = "";
// 罗马数字对应的数字值
int value[] = {1000, 900, 500, 400, 100, 90, 50, 40, 10, 9, 5, 4, 1};
// 数字对应罗马数字的值
String str[] = {"M", "CM", "D", "CD", "C", "XC", "L", "XL", "X", "IX", "V", "IV", "I"};
// 一共十三个对应关系,循环十三遍
for (int i = 0; i < 13; i++) {
// 当while循环继续的时候,说明当前位有值
while (num >= value[i]) {
// 当前数字减去这一位
num -= value[i];
// 结果数组加上这一位对应的罗马数字
res += str[i];
}
}
// 返回结果
return res;
}
public static String intToRomanII(int num) {
// 根据题目,最多四位数,将每一位提取出来,分别匹配
int a = num % 10;
num /= 10;
int b = num % 10;
num /= 10;
int c = num % 10;
num /= 10;
int d = num % 10;
return num4(d) + num3(c) + num2(b) + num1(a);
}
// 千位
public static String num4(int d) {
String res = "";
switch (d) {
case 1:
res = "M";
break;
case 2:
res = "MM";
break;
case 3:
res = "MMM";
break;
case 0:
res = "";
break;
}
return res;
}
// 百位
public static String num3(int c) {
String res = "";
switch (c) {
case 1:
res = "C";
break;
case 2:
res = "CC";
break;
case 3:
res = "CCC";
break;
case 4:
res = "CD";
break;
case 5:
res = "D";
break;
case 6:
res = "DC";
break;
case 7:
res = "DCC";
break;
case 8:
res = "DCCC";
break;
case 9:
res = "CM";
break;
case 0:
res = "";
break;
}
return res;
}
// 十位
public static String num2(int b) {
String res = "";
switch (b) {
case 1:
res = "X";
break;
case 2:
res = "XX";
break;
case 3:
res = "XXX";
break;
case 4:
res = "XL";
break;
case 5:
res = "L";
break;
case 6:
res = "LX";
break;
case 7:
res = "LXX";
break;
case 8:
res = "LXXX";
break;
case 9:
res = "XC";
break;
case 0:
res = "";
break;
}
return res;
}
// 个位
public static String num1(int a) {
String res = "";
switch (a) {
case 1:
res = "I";
break;
case 2:
res = "II";
break;
case 3:
res = "III";
break;
case 4:
res = "IV";
break;
case 5:
res = "V";
break;
case 6:
res = "VI";
break;
case 7:
res = "VII";
break;
case 8:
res = "VIII";
break;
case 9:
res = "IX";
break;
case 0:
res = "";
break;
}
return res;
}
}
- C语言版
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
char * intToRoman(int num)
{
// 开辟结果数组空间
char *res = (char *)malloc(20 * sizeof(char));
/*LeetCode的gcc版本问题,避免缓存越界*/
memset(res, 0, sizeof(char) * 20);
// 罗马数字对应的数字值
int value[13] = { 1000,900,500,400,100,90,50,40,10,9,5,4,1 };
// 数字对应罗马数字的值
char str[13][3] = { "M","CM","D","CD","C","XC","L","XL","X","IX","V","IV","I" };
// 一共十三个对应关系,循环十三遍
for (int i = 0; i < 13; i++)
{
// 当while循环继续的时候,说明当前位有值
while (num >= value[i])
{
// 当前数字减去这一位
num -= value[i];
// 结果数组加上这一位对应的罗马数字
strcat(res, str[i]);
}
}
// 返回结果
return res;
}
/*主函数省略*/
十【提交结果】
-
Java语言版
-
C语言版