罗马数字包含以下七种字符: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:
输入: "III" 输出: 3
示例 2:
输入: "IV" 输出: 4
示例 3:
输入: "IX" 输出: 9
示例 4:
输入: "LVIII" 输出: 58 解释: C = 100, L = 50, XXX = 30, III = 3.
示例 5:
输入: "MCMXCIV" 输出: 1994 解释: M = 1000, CM = 900, XC = 90, IV = 4.
在网上找了一种其他简单的思路:即当前字符比相邻右边的字符对应的值小时,只需要直接在结果中减去当前字符的值,否则加上当前字符的值。但是这种思路不够严谨,因为没有考虑到相邻字符的输入是否合法。提交代码如下:int romanToInt(char* s) { char key[7]={'I','V','X','L','C','D','M'}; int val[7]={1,5,10,50,100,500,1000}; int result=0; while(*s!='\0' && *(s+1)!='\0') { int i=0; for(i=0;i<7;i++)//找到s当前字符对应的key数组的下标,便于计算当前字符对应的数值 { if(*s==key[i]) { break; } } if(i==7)//出现了key数组以外的字符,认为是非法输入 { printf("invalide input s!\n"); return 0; } if(*(s)==key[6])//判断当前字符是否是M,如果是,直接计算M的个数 { int count=0; while(*s==key[6]) { count++; s++; } result+=val[6]*count; } else if((*(s+1)==key[i+1])||((*s!=key[5])&&(*(s+1)==key[i+2])))//判断相邻两个字符是否是减法关系 { printf("*s=%c,*(s+1)=%c\n",*s,*(s+1)); printf("result=%d,val[i+1]=%d,val[i]=%d\n",result,val[i+1],val[i]); if(*(s+1)==key[i+1]) { result+=(val[i+1]-val[i]); } if(*(s+1)==key[i+2]) { result+=(val[i+2]-val[i]); } printf("result=%d\n",result); s+=2; } else//判断字符是否是重复,计算加法 { int count=0; while(*s==key[i]) { count++; s++; } result+=val[i]*count; } } if(*s!='\0') { int i=0; for(i=0;i<7;i++)//找到s当前字符对应的key数组的下标,便于计算当前字符对应的数值 { if(*s==key[i]) { break; } } if(i==7)//出现了key数组以外的字符,认为是非法输入 { printf("invalide input s!\n"); return 0; } result+=val[i]; } return result; }
int chPos(char ch)//找出字符对应的数组索引 { char key[7]={'I','V','X','L','C','D','M'}; int i=0; for(i=0;i<7;i++) { if(key[i]==ch) { break; } } return i;//i==7表示有异常输入 } int romanToInt(char* s) { char key[7]={'I','V','X','L','C','D','M'}; int val[7]={1,5,10,50,100,500,1000}; int result=0; int s0=chPos(*s); int s1=chPos(*(s+1)); while(*s!='\0' && *(s+1)!='\0')//算法思路:字符比相邻右边的字符对应的val小,那么直接减去该字符对应的数字,否则加上该字符对应的数字 { if(s0==7 || s1==7) { printf("异常输入字符\n"); return 0; } if(val[s0]<val[s1]) { result-=val[s0]; } else { result+=val[s0]; } s0=s1; s1=chPos(*(s+2)); s++; } int fin=chPos(*s); if(fin==7) { printf("异常输入字符\n"); return 0; } result+=val[fin]; return result; }