Ejercicio 03 — Ignorando no-alfanuméricos y mayúsculas, determina si s es palíndromo

Dificultad: verde · Módulo 09 (Puente a NeetCode)

Enunciado

ignorando no-alfanuméricos y mayúsculas, determina si s es palíndromo

Cómo se resuelve

Comprobar si algo es palíndromo es el ejercicio canónico de dos punteros: dos índices que arrancan en los extremos y se cierran hacia el centro comparando por parejas.

  1. limpia = [c.lower() for c in s if c.isalnum()] — primero normalizamos. El enunciado pide ignorar signos, espacios y mayúsculas, así que nos quedamos solo con caracteres alfanuméricos (isalnum()) pasados a minúscula. Sin esto compararíamos comas y espacios.
  2. left = 0 y right = len(limpia) - 1 colocan un puntero en cada extremo de la cadena limpia.
  3. while left < right: avanza mientras no se crucen. Si en algún par limpia[left] != limpia[right], no es palíndromo y devolvemos False de inmediato. Si coinciden, left += 1 y right -= 1 acercan ambos al centro.
  4. Solo hace falta recorrer media cadena (los punteros se encuentran en el medio): O(n) tiempo. El espacio es O(n) por la lista limpia.

Trampa habitual: creer que s == s[::-1] es equivalente. Sobre la cadena original fallaría por los signos y las mayúsculas; funcionaría solo sobre limpia, pero entonces construyes una segunda lista invertida. Los dos punteros comparan in situ sin copiar nada extra.

Para practicar — cópialo y complétalo

Pega este esqueleto y completa los TODO. Es la mejor forma de aprender: inténtalo antes de mirar la solución.

# Curso de Python — Modulo 09: Puente a NeetCode
# Ejercicio 03 — PRACTICA (rellena los TODO)
# Enunciado: ignorando no-alfanuméricos y mayúsculas, determina si s es palíndromo
# Dificultad: verde
# Ejecutar: python3 ej03_practica.py
 
# PISTA: usa c.isalnum() para filtrar y c.lower() para normalizar.
# Despues aplica dos punteros: left=0, right=len-1, avanza ambos hacia el centro.
 
 
def is_palindrome(s: str) -> bool:
    """Devuelve True si s es palindromo ignorando no-alfanumericos y mayusculas."""
    # TODO 1: construye una lista 'limpia' con los caracteres de s
    #         que sean alfanumericos (c.isalnum()) convertidos a minuscula (c.lower())
    #         Usa una list comprehension: [... for c in s if ...]
    limpia = ...
 
    # TODO 2: inicializa left = 0 y right = ultimo indice de limpia
    left = ...
    right = ...
 
    # TODO 3: bucle while left < right
    while ...:
        # TODO 4: si limpia[left] != limpia[right], devuelve False
        if ...:
            return ...
 
        # TODO 5: mueve ambos punteros hacia el centro
        left += ...
        right -= ...
 
    # TODO 6: si el bucle termina sin encontrar diferencias, devuelve True
    return ...
 
 
# --- Pruebas (no toques esta parte) ---
if __name__ == "__main__":
    casos = [
        ("A man, a plan, a canal: Panama", True),
        ("race a car",                     False),
        (" ",                              True),
        ("Was it a car or a cat I saw?",   True),
    ]
 
    for s, esperado in casos:
        resultado = is_palindrome(s)
        estado = "OK" if resultado == esperado else "FALLO"
        print(f"[{estado}] is_palindrome({s!r}) = {resultado}  (esperado {esperado})")

Solución — cópiala y ejecútala

# Curso de Python — Modulo 09: Puente a NeetCode
# Ejercicio 03 — MODELO (resuelto)
# Enunciado: ignorando no-alfanuméricos y mayúsculas, determina si s es palíndromo
# Dificultad: verde
# Ejecutar: python3 ej03_modelo.py
 
# PATRON: dos punteros (left y right) que avanzan hacia el centro.
# Primero limpiamos la cadena: nos quedamos solo con caracteres
# alfanumericos en minusculas. Luego comparamos desde los extremos.
# Coste: O(n) tiempo, O(n) espacio (por la lista limpia).
 
 
def is_palindrome(s: str) -> bool:
    """Devuelve True si s es palindromo ignorando no-alfanumericos y mayusculas."""
    # Paso 1: filtrar y normalizar
    limpia = [c.lower() for c in s if c.isalnum()]
 
    # Paso 2: dos punteros
    left = 0
    right = len(limpia) - 1
 
    while left < right:
        if limpia[left] != limpia[right]:
            return False   # par no coincide -> no es palindromo
        left += 1
        right -= 1
 
    return True   # todos los pares coincidieron
 
 
# --- Pruebas manuales ---
if __name__ == "__main__":
    casos = [
        ("A man, a plan, a canal: Panama", True),
        ("race a car",                     False),
        (" ",                              True),   # cadena vacia/espacio -> True
        ("Was it a car or a cat I saw?",   True),
    ]
 
    for s, esperado in casos:
        resultado = is_palindrome(s)
        estado = "OK" if resultado == esperado else "FALLO"
        print(f"[{estado}] is_palindrome({s!r}) = {resultado}  (esperado {esperado})")

Cómo usarlo

Pega el código en un fichero y ejecútalo con tu toolchain habitual (o el botón de Ejecutar de tu editor). Antes de mirar la solución, intenta completar tú el esqueleto: es la mejor forma de aprender.

Conexiones