Ejercicio 05 — Dadas dos cadenas s y t, devuelve True si t es un anagrama de s
Dificultad: verde · Módulo 09 (Puente a NeetCode)
Enunciado
dadas dos cadenas s y t, devuelve True si t es un anagrama de s
Cómo se resuelve
Dos palabras son anagramas si tienen las mismas letras con las mismas frecuencias: el patrón es contar apariciones, y collections.Counter lo hace en una línea.
if len(s) != len(t): return False— atajo barato. Si tienen distinto número de caracteres, es imposible que sean anagramas, y así evitamos trabajo innecesario.Counter(s)construye un dict{caracter: frecuencia}recorriendo la cadena.Counter(s) == Counter(t)esTruecuando ambos tienen exactamente las mismas claves con los mismos valores. Todo en O(n) tiempo y O(k) espacio (k = letras distintas).- La versión manual muestra lo que hace Counter por dentro:
conteo[c] = conteo.get(c, 0) + 1suma uno por cada letra des, y luego- 1por cada letra det.get(c, 0)devuelve 0 si la clave aún no existe, evitando elKeyError. all(v == 0 for v in conteo.values())cierra la idea: si sumarsy restartdeja todos los contadores a cero, cada letra apareció el mismo número de veces en ambas. Si alguno queda distinto de cero, hay desajuste.
Trampa habitual: usar sorted(s) == sorted(t). Funciona, pero ordenar cuesta O(n log n); el conteo con dict/Counter es O(n). En una entrevista, el conteo es la respuesta que buscan por ser más eficiente.
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 05 — PRACTICA (rellena los TODO)
# Enunciado: dadas dos cadenas s y t, devuelve True si t es un anagrama de s
# Dificultad: verde
# Ejecutar: python3 ej05_practica.py
# PISTA: collections.Counter(cadena) devuelve un dict {caracter: frecuencia}.
# Dos Counter son iguales con == si tienen las mismas letras con las mismas frecuencias.
# Bonus: intenta tambien la version manual con dict y .get(c, 0).
from collections import Counter
def is_anagram(s: str, t: str) -> bool:
"""Devuelve True si t es un anagrama de s."""
# TODO 1: si len(s) != len(t) devuelve False directamente
if ...:
return ...
# TODO 2: compara Counter(s) con Counter(t) y devuelve el resultado
return ...
# --- Pruebas (no toques esta parte) ---
if __name__ == "__main__":
casos = [
("anagram", "nagaram", True),
("rat", "car", False),
("a", "a", True),
("ab", "a", False),
]
for s, t, esperado in casos:
resultado = is_anagram(s, t)
estado = "OK" if resultado == esperado else "FALLO"
print(f"[{estado}] is_anagram({s!r}, {t!r}) = {resultado} (esperado {esperado})")Solución — cópiala y ejecútala
# Curso de Python — Modulo 09: Puente a NeetCode
# Ejercicio 05 — MODELO (resuelto)
# Enunciado: dadas dos cadenas s y t, devuelve True si t es un anagrama de s
# Dificultad: verde
# Ejecutar: python3 ej05_modelo.py
# PATRON: conteo de frecuencias con collections.Counter.
# Dos cadenas son anagramas si tienen exactamente las mismas letras
# con las mismas frecuencias. Counter crea un dict {caracter: frecuencia}
# y dos Counter son iguales (==) si tienen las mismas claves y valores.
#
# ALTERNATIVA MANUAL (sin Counter): usar un dict propio para contar.
# La mostramos como version 2 para entender que hace Counter por dentro.
from collections import Counter
def is_anagram(s: str, t: str) -> bool:
"""Devuelve True si t es un anagrama de s."""
# Longitudes distintas -> imposible ser anagrama
if len(s) != len(t):
return False
return Counter(s) == Counter(t)
def is_anagram_manual(s: str, t: str) -> bool:
"""Misma logica, implementada a mano con dict para entender el mecanismo."""
if len(s) != len(t):
return False
conteo = {}
# Sumamos 1 por cada letra en s
for c in s:
conteo[c] = conteo.get(c, 0) + 1
# Restamos 1 por cada letra en t
for c in t:
conteo[c] = conteo.get(c, 0) - 1
# Si algun valor no es 0, hay diferencia de frecuencias
return all(v == 0 for v in conteo.values())
# --- Pruebas manuales ---
if __name__ == "__main__":
casos = [
("anagram", "nagaram", True),
("rat", "car", False),
("a", "a", True),
("ab", "a", False),
]
for s, t, esperado in casos:
r1 = is_anagram(s, t)
r2 = is_anagram_manual(s, t)
e1 = "OK" if r1 == esperado else "FALLO"
e2 = "OK" if r2 == esperado else "FALLO"
print(f"[{e1}] Counter: {r1} [{e2}] manual: {r2} s={s!r} t={t!r}")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.