https://leetcode-cn.com/problems/roman-to-integer/ Римские
цифры к целым числам
Римские цифры содержат следующие семь символов: 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, и представленное число равно числу 4, полученному путем уменьшения числа 1 на число 5. Точно так же число 9 представлено как IX. Это специальное правило применяется только к следующим шести ситуациям:
Я могу быть размещен слева от V (5) и X (10) для обозначения 4 и 9.
X может быть размещен слева от L (50) и C (100) для обозначения 40 и 90.
C может быть размещен слева от D (500) и M (1000) для обозначения 400 и 900.
Получив римскую цифру, преобразуйте ее в целое число. Вход должен быть в диапазоне от 1 до 3999.
Пример 1:
Вход: «III»
Выход: 3
Пример 2:
Вход: "IV"
Выход: 4
Пример 3:
Вход: "IX"
Выход: 9
Пример 4:
Вход: "LVIII"
Выход: 58
Пояснение: L = 50, V = 5, III = 3.
Пример 5:
Вход: "MCMXCIV"
Выход: 1994
Объяснение: M = 1000, CM = 900, XC = 90, IV = 4.
Решение 1
Используйте карту.
Ключ представляет собой одну букву римских цифр, а val - соответствующее значение.
Потребности , чтобы определить ключ , соответствующий тому , что теперь Допустимы не меньше , чем на следующий ключ , соответствующий ВАЛ, такие как IV
четыре вместо шести.
40 мс 9,1 мб, для построения карты требуется время, сложность времени следующей операции составляет O (n).
class Solution {
public:
int romanToInt(string s) {
map<char, int> m = {
{'I', 1},
{'V', 5},
{'X', 10},
{'L', 50},
{'C', 100},
{'D', 500},
{'M', 1000},
};
int ret = 0;
for (int i = 0; i < s.size(); ++i) {
if (m[s[i]] < m[s[i + 1]]) {
ret = ret - m[s[i]];
} else {
ret = ret + m[s[i]];
}
}
return ret;
}
};
Решение 2
Решение для пользователей сети 4ms 5.6mb,
#define nI 1 //直接用define I 1,好像会有歧义
#define nV 5
#define nX 10
#define nL 50
#define nC 100
#define nD 500
#define nM 1000
int romanToInt(char* s)
{
int num = 0, flag = 0; /*立一个flag,是因为之前我在后面会用三个if,一个else,其实我的初衷是三个if有其中任何一个满足都不要再执行else了
但是如果没有flag的话,意思是第三个if如果不成立便会跳去else,比如IV,第一个if满足,然后第三个if不满足,else这时候
就会出来执行,很不爽*/
while(*s != NULL)
{
if(*s == 'I' && (*(s + 1) == 'V' || *(s + 1) == 'X')) //接下来的这三个if都有特殊含义,所以flag=1,普通情况属于flag=0
{
flag = 1;
switch(*(s + 1))
{
case 'V':num += (nV - nI); s+=2; break;
case 'X':num += (nX - nI); s+=2; break;
}
}
if(*s == 'X' && (*(s + 1) == 'L' || *(s + 1) == 'C'))
{
flag = 1;
switch(*(s + 1))
{
case 'L':num += (nL - nX); s+=2; break;
case 'C':num += (nC - nX); s+=2; break;
}
}
if(*s == 'C' && (*(s + 1) == 'D' || *(s + 1) == 'M'))
{
flag = 1;
switch(*(s + 1))
{
case 'D':num += (nD - nC); s+=2; break;
case 'M':num += (nM - nC); s+=2; break;
}
}
if(flag == 0) //本来这里是else的,改为if(flag == 0)
{
switch(*s)
{
case 'I':num += nI; s += 1; break;
case 'V':num += nV; s += 1; break;
case 'X':num += nX; s += 1; break;
case 'L':num += nL; s += 1; break;
case 'C':num += nC; s += 1; break;
case 'D':num += nD; s += 1; break;
case 'M':num += nM; s += 1; break;
}
}
flag = 0; //最后置回普通状态
}
return num;
}
EOF