题目描述:
算法思想:罗马数字一般情况下直接从左向右依次读取即可,但是存在特殊情况使得读取结果会出现偏差,因为我们需要对特殊情况进行处理,即当出现I、X、C时讨论其左右的字符,对相应的整数进行加或减的运算。
例如:输入IV,首先读入I,我们判定其为数字1,如果此时直接循环读取下一个字符V,因为其左侧的字符为I,因此需要对整数进行减一操作,我们会得到 -1,当再一次进行读取时,程序告诉我们字符已经读取结束,循环便不会进入,因此程序错误。但是算法本身并没有问题,因此可以从算法的顺序出发看看能否通过修改算法实现顺序来达到我们的目的。即,在碰到特殊情况时我们先判断其两侧的数据情况,而不是单单从左到右依次读入字符进行处理。
因此在新的算法之下,处理IV字符,我们的顺序是:读入I,发现属于特殊情况,我们判断两侧的情况,I左侧没有字符,右侧字符为V,故我们要对整数进行减一操作,然后读入V,发现不属于特殊情况,故直接将整数进行加五操作即可,最后得到正确的答案:4。
不难看出,我们需要对特殊情况的字符所代表的数字进行保存,已使得在循环时可以直接输出相应的操作,故使用switch语句,当字符没有读完时进行读入字符。
/*int romanToInt(char * s) //指针版本
{
int count = 0;
while (*s)
{
if (*s == 'V') count += 5;
else if (*s == 'L') count += 50;
else if (*s == 'D') count += 500;
else if (*s == 'M') count += 1000;
else if (*s == 'I') //处理题目给定条件
count = (*(s + 1) == 'V' || *(s + 1) == 'X') ? count - 1 : count + 1;
else if (*s == 'X')
count = (*(s + 1) == 'L' || *(s + 1) == 'C') ? count - 10 : count + 10;
else
count = (*(s + 1) == 'D' || *(s + 1) == 'M') ? count - 100 : count + 100;
s++;
}
return count;
}*/
int romanToInt(char * s) //数组版本
{
int count = 0, i = 0;
while (s[i])
{
if (s[i] == 'V') count += 5;
else if (s[i] == 'L') count += 50;
else if (s[i] == 'D') count += 500;
else if (s[i] == 'M') count += 1000;
else if (s[i] == 'I') //处理题目给定条件
count = (s[i + 1] == 'V' || s[i + 1] == 'X') ? count - 1 : count + 1;
else if (s[i] == 'X')
count = (s[i + 1] == 'L' || s[i + 1] == 'C') ? count - 10 : count + 10;
else
count = (s[i + 1] == 'D' || s[i + 1] == 'M') ? count - 100 : count + 100;
i++;
}
return count;
}
为了方便起见,代码中对于特殊情况的处理使用了三目运算符(?:),三目运算符(?:)相当于if-else语句的缩减版本。解释如下:
expression1?expression2:expression3
当expression1为真时,整个表达式的值是expression2,否则表达式的值为expression3。
例如:num = (6 > 5) ? 1 : 0,num的值(当6 > 5时)为1,否则为0,显然num为1。
本题中,第一个三目运算符解释为:当读入的字符为I时,如果右侧的字符为V,或者右侧的字符为X时,count减一,否则(说明字符I是单独存在的,故直接执行)count加一。