[Una pregunta por día] Números romanos a enteros

https://leetcode-cn.com/problems/roman-to-integer/Números
romanos a enteros
Los números romanos contienen los siguientes siete caracteres: I, V, X, L, C, D y M.

Valor de caracteres
I 1
V 5
X 10
L 50
C 100
D 500
M 1000
Por ejemplo, el número romano 2 se escribe como II, que es dos paralelos 1. 12 se escribe como XII, que es X + II. 27 Escribe XXVII, que es XX + V + II.

Normalmente, el número pequeño en números romanos está a la derecha del número grande. Pero hay casos especiales, por ejemplo, 4 no está escrito como IIII, sino IV. El número 1 está a la izquierda del número 5, y el número representado es igual al número 4 obtenido al reducir el número 1 por el número 5. Del mismo modo, el número 9 se representa como IX. Esta regla especial solo se aplica a las siguientes seis situaciones:

Puedo colocarme a la izquierda de V (5) y X (10) para representar 4 y 9.
X se puede colocar a la izquierda de L (50) y C (100) para indicar 40 y 90.
C se puede colocar a la izquierda de D (500) y M (1000) para indicar 400 y 900.
Dado un número romano, conviértalo a un número entero. La entrada debe estar en el rango de 1 a 3999.

Ejemplo 1:

Entrada: "III"
Salida: 3
Ejemplo 2:

Entrada: "IV"
Salida: 4
Ejemplo 3:

Entrada: "IX"
Salida: 9
Ejemplo 4:

Entrada: "LVIII"
Salida: 58
Explicación: L = 50, V = 5, III = 3.
Ejemplo 5:

Entrada: "MCMXCIV"
Salida: 1994
Explicación: M = 1000, CM = 900, XC = 90, IV = 4.


Solución 1

Usa el mapa.
La clave es una sola letra de números romanos, y val es el valor correspondiente.
Necesidades para determinar la tecla que corresponde a lo que es ahora val no es menos de la siguiente tecla que corresponde val, tales como IVcuatro en lugar de seis.
40ms 9.1mb, lleva tiempo construir el mapa, la siguiente complejidad de tiempo de operación es 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;
    }
};

Solución 2

La solución de los internautas es 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

Se han publicado 98 artículos originales · 91 alabanzas · Más de 40,000 visitas

Supongo que te gusta

Origin blog.csdn.net/Hanoi_ahoj/article/details/105299608
Recomendado
Clasificación