Para tratar de mantenerme activo en LeetCode y para practicar un poco mi PHP decidí resolver este problema para convertir números romanos a números decimales, y después de algunos intentos que no cumplían los test llegué a esta solución que sí los pasó todos:
class Solution {
/**
* @param String $s
* @return Integer
*/
function romanToInt($s) {
$_numbers = [
'I' => 1,
'V' => 5,
'X' => 10,
'L' => 50,
'C' => 100,
'D' => 500,
'M' => 1000
];
$total = 0;
$prev = 0;
foreach (str_split($s) as $c) {
$current = $value = $_numbers[$c];
if ($prev > 0 && $current > $prev) {
$value = $current - 2 * $prev;
}
$total += $value;
$prev = $current;
}
return $total;
}
}
Solución correcta y el enfoque es el estándar para este problema.
Un comentario:
$current = $value = $_numbers[$c]— asignas dos variables en una línea para luego pisar$valuecondicionalmente. Es válido pero ligeramente confuso;$currenty$valuearrancan iguales y eso no es obvio a primera lectura.La lógica de
$current - 2 * $preves el truco interesante — explícame por qué el2 *.
Hasta me sentí en examen, yo creo que piensa que le pedí ayuda a Gemini. Mi explicación fue la siguiente:
Al sumar siempre el valor actual y al encontrar que este valor actual es mayor al que se sumó en la iteración anterior, doy por hecho que ese valor anterior forma parte de un "número compuesto" con el valor actual, entonces tengo que obtener la diferencia del actual (que es mayor) y el anterior (que es menor) y dicha diferencia representa realmente el valor del "número compuesto"; pero como el número anterior menor ya se sumó al total en su propia iteración, debo quitarlo del valor real del "número compuesto" recién determinado.
Exacto. Es una forma elegante de no tener que hacer lookahead — lees hacia adelante implícitamente al detectar que el actual es mayor que el anterior. Big O: O(n) tiempo, O(1) espacio si ignoras el str_split que crea un array. Si lo cuentas, O(n) espacio. En una entrevista vale la pena mencionarlo.

Comentarios
Publicar un comentario