Soluciones LeetCode
#9 — Número palíndromo

Del truco con cadena a la inversión parcial — lógica entera limpia

Arte ASCII a color: una computadora anticuada sobre un escritorio con una estantería al fondo, que sugiere un espacio de trabajo clásico para programar.
Ilustración en estilo ASCII: una computadora anticuada sobre un escritorio con una estantería detrás.

Enunciado del problema

Dado un entero x, devuelve true si x es un palíndromo, y false en caso contrario.

Ejemplo 1:

Ejemplo 2:

Ejemplo 3:

Restricciones:

  • -2³¹ <= x <= 2³¹ - 1

Seguimiento: ¿Podrías resolverlo sin convertir el entero a cadena?

El enfoque ingenuo

La solución más directa es convertir el entero a cadena y verificar si se lee igual al revés. Es breve, legible y pasa todos los casos de prueba fácilmente, pero usa memoria extra y evita el verdadero desafío.

Python

def esPalindromo_cadena(x: int) -> bool:
    s = str(x)
    return s == s[::-1]
            

Complejidad inicial

Tiempo: O(n), donde n es el número de dígitos (≈ log₁₀(x)).
Espacio: O(n) para la representación como cadena.

Esto es aceptable dadas las restricciones (máximo 10 dígitos), pero el seguimiento pide una solución sin conversión a cadena — y es más interesante trabajar directamente con el número.

Invirtiendo sin cadenas

Un enfoque numérico: invertir el entero y compararlo con el original. Los números negativos nunca son palíndromos (el signo menos rompe la simetría), y los números que terminan en 0 (excepto el 0 mismo) no pueden ser palíndromos porque el reverso tendría un cero a la izquierda.

El método obvio es construir el número invertido extrayendo dígitos con % 10 y // 10. Pero invertir el número completo puede causar desbordamiento en lenguajes con enteros de ancho fijo. Un enfoque más inteligente: invertir solo la mitad del número y compararla con la otra mitad.

¿Cómo sabemos que hemos llegado a la mitad? Mientras el número original x sea mayor que la mitad invertida mitad_invertida, seguimos moviendo dígitos de x a mitad_invertida.

Python

def esPalindromo(x: int) -> bool:
    # los números negativos no son palíndromos
    # además, si el último dígito es 0, solo el 0 mismo puede ser palíndromo
    if x < 0 or (x % 10 == 0 and x != 0):
        return False

    mitad_invertida = 0
    while x > mitad_invertida:
        mitad_invertida = mitad_invertida * 10 + x % 10
        x //= 10

    # Para longitud par: x == mitad_invertida
    # Para longitud impar: x == mitad_invertida // 10 (el dígito del medio no importa)
    return x == mitad_invertida or x == mitad_invertida // 10
            

Veamos la traza para x = 1221 (longitud par) y x = 121 (longitud impar):

Simulación paso a paso: inversión parcial para x = 1221
Paso x (restante) mitad_invertida Condición (x > mitad_invertida) Acción
inicial 1221 0 Verdadero Entrar al bucle
1 122 1 Verdadero Continuar
2 12 12 Falso (12 > 12 es falso) Salir del bucle
Después del bucle: x = 12, mitad_invertida = 12. Son iguales → palíndromo.
Simulación paso a paso: inversión parcial para x = 121
Paso x (restante) mitad_invertida Condición Acción
inicial 121 0 Verdadero Entrar al bucle
1 12 1 Verdadero Continuar
2 1 12 Falso (1 > 12 falso) Salir del bucle
Después del bucle: x = 1, mitad_invertida = 12. Verificamos x == mitad_invertida // 10 → 1 == 1 → palíndromo.

El truco con números de longitud impar: el dígito del medio termina en la última posición de mitad_invertida, así que lo descartamos con división entera.

Complejidad final

Complejidad temporal: O(log₁₀(x)) — procesamos aproximadamente la mitad de los dígitos.
Complejidad espacial: O(1) — solo unas pocas variables enteras, sin estructuras adicionales.

Esta solución respeta las restricciones, evita el desbordamiento y cumple con el requisito de seguimiento. Es una forma limpia y matemática de verificar palíndromos.

A veces la respuesta más elegante no necesita ni un solo carácter — solo unos dígitos invertidos.

Referencias y lecturas adicionales

¿No te cansas de lumænaut? Lee esto...