前言
关于罗马数字转化为整数,可以建立起罗马数字与其代表值之间的一一对应关系,方便处理数据,进行相加
一、思路
建立一一对应关系:
先观察罗马数字串,发现共有13种情况,要把13种情况与单个罗马数字建立一一对应关系需要两个int数组,如下:
int num[7] = {1, 5, 10, 50, 100, 500, 1000};
char ch[7] = {'I', 'V', 'X', 'L', 'C', 'D', 'M'};
int num1[7] = {1, 4, 9, 40, 90,400, 900};//对于IV,IX等的特殊情况
处理字符串时,进行遍历,由于有两个罗马数字表示一个数值的特殊情况,所以要在一次遍历循环中把下一个字符也与char数组进行匹配,如果下一个字符的数值大于当前字符,则出现特殊情况,进行特殊处理
二、完整代码
#include <stdio.h>
#include <string.h>
int romanToInt(char *s);
int main()
{
char s[7] = "MCMXCIV";
printf("%d",romanToInt(s));
}
int romanToInt(char *s)
{
int num[7] = {1, 5, 10, 50, 100, 500, 1000};
char ch[7] = {'I', 'V', 'X', 'L', 'C', 'D', 'M'};
int numSep[7] = {1, 4, 9, 40, 90,400, 900};
int sum = 0;
int sign=0;
for (int i = 0; i < strlen(s); i++)//遍历字符数组
{
for (int j = 0; j < 7; j++)//对当前字符进行匹配
{
if (s[i] == ch[j])
{
for (int o = 0; o < 7; o++)//匹配成功后,对下一个字符匹配,检查是否是特殊情况
{
if (i + 1 < strlen(s) && s[i + 1] == ch[o] && o > j)
{
sum = sum + numSep[o];
i=i+1;//本次多查一位字符,防止再次查询
sign=1;
break;
/*
break停止的是当前for循环,
而我们需要最外层for循环遍历下一个字符,
所以设置了一个sign参数,多加一次break
*/
}
}
if(sign==1)
{
sign=0;
break;//最外层for循环遍历下一个字符
}
sum=sum+num[j];//非特殊情况
}
}
}
return sum;
}
三、另解
通过观察,我们发现当字符比后一个字符小时,这两个字符的值是后一个字符代表的值减前面的值,所以还有其他的方法解决问题
如下:
int romanToInt(char * s){
int n=strlen(s);
int num=0,i=0,j=0,k=0;;
int a[16];
for(i=0;i<n;i++){
switch(s[i]){
case 'I':a[i]=1;break;
case 'V':a[i]=5;break;
case 'X':a[i]=10;break;
case 'L':a[i]=50;break;
case 'C':a[i]=100;break;
case 'D':a[i]=500;break;
default :a[i]=1000;break;
} //按序存储字符对应10进制数字
}
for(i=0;i<n-1;i++){
if(a[i]>=a[i+1]){
num+=a[i];
}
else{
num+=a[i+1]-a[i];
i++;
}
}
if(n==1)return a[0]; //一位罗马数情况
if(a[n-1]<=a[n-2])
num+=a[n-1]; //末尾补位
return num;
}
/*作者:hzy-75
链接:https://leetcode.cn/problems/roman-to-integer/solution/by-hzy-75-kpug/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
*/
总结
以上就是今天要讲的内容,本文提供了两个解法,如有其他优秀的解法,还请指教哦。