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

Diagramas de flujo

Diagrama de flujo (actividad) del ejercicio 03

Diagrama de flujo (grafo) del ejercicio 03

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})")

Ejecútalo en el navegador

▶ Visualízalo paso a paso en Python Tutor — ve cómo cambian las variables línea a línea.

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