[Один вопрос в день] Римские цифры в целые числа

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

Опубликовано 98 оригинальных статей · 91 похвала · 40000+ просмотров

рекомендация

отblog.csdn.net/Hanoi_ahoj/article/details/105299608