罗马数字包含以下七种字符: 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)看到这个题,我首先想到的就是取得传入 的各个数字,由于题目已经限定了传入的数字在1-3999之间,所以我用了一个int型的nums数组来存放获取到的各个位,数组的下标分别是0-3,一次表示个位,十位, 百位,千位上的数字,如果没有的话就是0;
(2)其次我将题目中描述的字符与数值的对应关系放到直接放到了一个char *的数组中,便于之后使用;
(3)接着,就是从高位开始遍历nums数组,按照规则,将各个位对应的字符追加到需要输出的字符串中。
实现代码如下:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char * intToRoman(int num){
int nums[4];
memset(nums, 0, sizeof(nums));
if(num<1 || num >3999){
return NULL;
}
char *map[]={"I", //1
"V", //5
"X", //10
"L", //50
"C", //100
"D", //500
"M"}; //1000
int tmp=num;
int ii=0;
while(tmp!=0){
int get_num=tmp%10;
nums[ii]=get_num;
ii++;
tmp=tmp/10;
}
static char ret_string[1024];
memset(ret_string, 0, sizeof(ret_string));
ii=3;
for(;ii>=0;ii--){
if(nums[ii]!=0 && ii ==3){
int tmp=1;
while(tmp<=nums[ii]){
strcat(ret_string, map[6]);
tmp++;
}
}else if(nums[ii]!=0 && ii ==2){
int tmp=1;
if(nums[ii]<=3){
while(tmp<=nums[ii]){
strcat(ret_string, map[4]);
tmp++;
}
}else if(nums[ii] == 4){
strcat(ret_string, map[4]);
strcat(ret_string, map[5]);
}else if(nums[ii] ==5){
strcat(ret_string, map[5]);
}else if(nums[ii] >=6 && nums[ii]<=8){
tmp=6;
strcat(ret_string, map[5]);
while(tmp<=nums[ii]){
strcat(ret_string, map[4]);
tmp++;
}
}else{
strcat(ret_string, map[4]);
strcat(ret_string, map[6]);
}
}else if(nums[ii]!=0 && ii ==1){
int tmp=1;
if(nums[ii]<=3){
while(tmp<=nums[ii]){
strcat(ret_string, map[2]);
tmp++;
}
}else if(nums[ii] == 4){
strcat(ret_string, map[2]);
strcat(ret_string, map[3]);
}else if(nums[ii] ==5){
strcat(ret_string, map[3]);
}else if(nums[ii] >=6 && nums[ii]<=8){
tmp=6;
strcat(ret_string, map[3]);
while(tmp<=nums[ii]){
strcat(ret_string, map[2]);
tmp++;
}
}else{
strcat(ret_string, map[2]);
strcat(ret_string, map[4]);
}
}else if(nums[ii]!=0 && ii ==0){
int tmp=1;
if(nums[ii]<=3){
while(tmp<=nums[ii]){
strcat(ret_string, map[0]);
tmp++;
}
}else if(nums[ii] == 4){
strcat(ret_string, map[0]);
strcat(ret_string, map[1]);
}else if(nums[ii] ==5){
strcat(ret_string, map[1]);
}else if(nums[ii] >=6 && nums[ii]<=8){
tmp=6;
strcat(ret_string, map[1]);
while(tmp<=nums[ii]){
strcat(ret_string, map[0]);
tmp++;
}
}else{
strcat(ret_string, map[0]);
strcat(ret_string, map[2]);
}
}
}
return ret_string;
}
方法二:
通过枚举出所有的可能性,建立个位,十位,百位,千位的数字与字符的对应关系即可
代码如下:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char * intToRoman(int num){
int nums[4];
memset(nums, 0, sizeof(nums));
static char ret_string[1024];
memset(ret_string, 0, sizeof(ret_string));
if(num<1 || num >3999){
return NULL;
}
char* map[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"}};
int tmp=num;
int ii=0;
while(tmp!=0){
int get_num=tmp%10;
nums[ii++]=get_num;
tmp=tmp/10;
}
ii=3;
for(;ii>=0;ii--){
if(nums[ii]!=0 ){
strcat(ret_string, map[ii][nums[ii]]);
}
}
return ret_string;
}
方法三:
贪心法则:我们每次尽量使用最大的数来表示。 比如对于 1994 这个数,如果我们每次尽量用最大的数来表示,依次选 1000,900,90,4,会得到正确结果 MCMXCIV。
所以,我们将哈希表按照从大到小的顺序排列,然后遍历哈希表,直到表示完整个输入。
代码如下:
class Solution {
public:
string intToRoman(int num) {
int values[] = {1000, 900, 500, 400, 100, 90, 50, 40, 10, 9, 5, 4, 1};
string reps[] = {"M", "CM", "D", "CD", "C", "XC", "L", "XL", "X", "IX", "V", "IV", "I"};
string res;
int
for (int i = 0; i < 13; i ++ ) //这里不使用图里的count了,一遍一遍来就行了
while(num >= values[i])
{
num -= values[i];
res += reps[i];
}
return res;
}
};
此代码为C++的代码。
作者:z1m
链接:https://leetcode-cn.com/problems/integer-to-roman/solution/tan-xin-ha-xi-biao-tu-jie-by-ml-zimingmeng/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/integer-to-roman
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。