fedorthinks

Curso exprés · No. 23

Una data structure no es más que una manera de organizar los datos para que las cosas que haces más a menudo sean rápidas. Elige la correcta y una operación es instantánea; elige la equivocada y la misma tarea se arrastra. Big-O es el lenguaje para esa diferencia — cómo crece el coste de una operación a medida que crecen los datos.

16 conceptos · un diagrama para cada uno · chuleta al final

§ 01

Antes de las estructuras concretas, la idea detrás de todas ellas. Una data structure no es algo académico — es la única decisión que más a menudo determina si tu código es rápido o dolorosamente lento.

El mapa: 16 conceptos en seis grupos

Un mapa de metro: primero ves todas las líneas, luego viajas estación por estación.

Arriba hay tres ideas básicas: Data Structure, Trade-off y Big-O. Debajo, seis grupos: las formas de crecimiento de Big-O, el array, el hash map y el set, las estructuras con orden (stack y queue), las estructuras con forma (tree y graph) y, por último, cómo elegir entre ellas en la práctica.

BasicsData structureTrade-offBig-OBig-O shapesO(1)O(log n)O(n)O(n²)ArrayArray / indexLinear searchInsert in middleHash mapHash mapHash functionSetOrderStack (LIFO)Queue (FIFO)ShapeTreeBalanced treeGraphUsing it wellDominant operationMap before loop
Tres ideas básicas arriba y seis grupos — los capítulos 2–7 las siguen.

Cómo leer este curso

Un pasaporte: los mismos campos para todos, así es fácil compararlos.

Cada concepto recibe el mismo tratamiento: su nombre en inglés (el término que encontrarás en la documentación y en las entrevistas), una imagen de la vida diaria, un diagrama y una ficha: qué es, cómo funciona, un ejemplo, el coste y cómo se relaciona con otras estructuras. La única regla de este curso: no existe la mejor estructura — solo la que encaja con la operación que más haces.

Data Structure — organizar los datos para las operaciones que más haces

Una caja de herramientas ordenada con ranuras etiquetadas frente a un montón de herramientas en un saco — las mismas herramientas, pero una te deja tomar la correcta al instante y la otra te obliga a hurgar cada vez.

Una data structure es una manera de disponer los datos en memoria. Distintas disposiciones hacen rápidas distintas operaciones: una es estupenda para buscar cosas por nombre, otra para mantener el orden, otra para tomar siempre el elemento más reciente. Todo el juego consiste en hacer coincidir la estructura con lo que harás más a menudo.

La misma tarea puede ser trivial o casi imposible según cómo se guarden los datos. Encontrar una palabra en un diccionario ordenado lleva segundos; encontrarla entre esas mismas palabras volcadas en orden aleatorio podría llevar todo el día. Así que una cantidad sorprendente de «haz esto rápido» es en realidad «guárdalo con la forma correcta». La estructura es la decisión.

Same data1 million usersPile in a listfind id 42 → check eachMap by idfind id 42 → jump thereslow · O(n)instant · O(1)
Los mismos datos: en un montón miramos uno por uno; en un map por id saltamos directos.
ConceptData Structure· cómo se disponen los datos
Qué es

Una manera de disponer los datos en memoria para operaciones concretas.

Cómo funciona

La disposición decide de antemano qué operaciones son baratas y cuáles caras.

Ejemplo

Buscar a un usuario por ID: instantáneo en una estructura, un suplicio por todo en otra.

Coste
Una mala elección no se arregla después con «optimización ingeniosa».
Relaciones

Las estructuras se comparan con Big-O y se eligen mediante un Trade-off.

Trade-off — toda estructura renuncia a algo

Un auto deportivo y un camión de mudanzas son ambos vehículos — no preguntas cuál es mejor, preguntas mejor para qué.

Ninguna estructura es la mejor en todo. Una ofrece búsqueda instantánea pero ningún orden; otra mantiene el orden pero es lenta de buscar; otra es rápida para añadir pero lenta para encontrar dentro. Eso es el trade-off: la fortaleza en una operación se paga con debilidad en otra. No hay almuerzo gratis — tu trabajo es elegir la compensación que encaja con tu uso.

fast atslow atArrayby index · appendsearch by value · insert midHash map / Setlookup by key · presenceno orderStack / Queueadd & take at the endsfind something inside
Cada estructura tiene su lado fuerte y su lado débil.
ConceptTrade-off· no hay almuerzo gratis
Qué es

La fortaleza de una estructura en una operación siempre cuesta debilidad en otra.

Ejemplo

Un Hash Map encuentra por clave al instante pero no guarda orden; un Array guarda el orden pero es lento al buscar por valor.

Cuándo pensarlo

Cada vez que decides dónde viven los datos: ¿qué hago a menudo y qué rara vez?

Relaciones

La compensación se mide en Big-O — cada operación tiene una «forma».

Una data structure organiza los datos para que tus operaciones comunes sean rápidas. La forma correcta vuelve fácil una tarea difícil — y toda estructura cambia velocidad en una operación por debilidad en otra.

§ 02

Para comparar estructuras necesitas una manera de hablar de velocidad que no dependa de la máquina. Big-O es ese lenguaje: mide cómo crece el trabajo a medida que crecen los datos.

Big-O notation — crecimiento, no segundos

Preguntar no cuánto tarda una entrega, sino cómo cambia el tiempo total a medida que la ruta pasa de diez paradas a diez mil — la forma del crecimiento, no la lectura de un cronómetro.

La notación Big-O describe cómo crece el coste de una operación a medida que crece la cantidad de datos, llamada n. Ignora los milisegundos exactos y la computadora concreta, y captura la forma: ¿duplicar los datos duplica el trabajo, lo cuadruplica, o apenas lo cambia? Esa forma es lo que decide si algo se mantiene rápido a escala, así que Big-O es cómo los ingenieros comparan enfoques sin llegar a ejecutarlos.

data size n →workO(1)O(log n)O(n)O(n²)
Cuanto mayor es n, más se separan las formas: O(1) y O(log n) casi no suben, O(n²) se dispara.
ConceptBig-O notation· complejidad asintótica
Qué es

Una descripción de cómo crece el trabajo al crecer el tamaño de datos n.

Cómo funciona

Se descartan los segundos exactos y los detalles del hardware; se conserva la forma del crecimiento.

Ejemplo

«Buscar en un array es O(n)»: diez veces más elementos — aproximadamente diez veces más trabajo.

Ojo
No dice cuántos segundos; dice cómo escala.
Relaciones
Las formas habituales son las Complexity classes.

Complexity classes — formas de excelente a pésima

Cuatro maneras en que una tarea escala: una se queda en un solo paso sin importar el montón, una crece con el montón, una explota como el montón al cuadrado, y una apenas crece aunque el montón lo haga.

Unas pocas formas cubren la mayoría del código:

  • O(1) — constante: el mismo tiempo sin importar el tamaño (tomar un elemento por index).
  • O(log n) — logarítmica: apenas crece aunque los datos se disparen (reducir la búsqueda a la mitad en cada paso).
  • O(n) — lineal: crece al ritmo de los datos (recorrer una lista).
  • O(n²) — cuadrática: explota (comparar cada elemento con todos los demás). La clásica «bien en pruebas, muere en producción».

Con diez elementos, cualquier estructura se siente instantánea — las diferencias no se notan. Big-O trata de lo que pasa cuando n se hace grande. Por eso las cosas se vuelven lentas «de repente» en producción: la mala forma siempre estuvo ahí, solo que oculta hasta que los datos crecieron.

shapen = 10 (your test)n = 1 billion (prod)O(1)1 step1 stepO(log n)~3 steps~30 stepsO(n)10 steps1 billion stepsO(n²)100 steps10¹⁸ — never ends
Con diez elementos de prueba todas las formas se parecen; con mil millones hay un abismo.
TermComplexity classes· O(1), O(log n), O(n), O(n²)
Qué es
Nombres para las formas típicas de crecimiento.
Ejemplo

Index de un array — O(1); búsqueda en un árbol equilibrado — O(log n); recorrer una lista — O(n); un bucle dentro de otro bucle — O(n²).

Ojo

O(n²) va bien con datos de prueba y se atasca minutos con un millón de registros.

Regla

O(1) y O(log n) sobreviven a la escala; O(n) es honesta; O(n²) es una alarma.

Relaciones

Map before loop es la principal manera de convertir O(n²) en O(n).

Big-O mide cómo crece el trabajo con los datos, no los segundos. O(1) y O(log n) sobreviven a la escala; O(n) es honesta; O(n²) va bien en pruebas y muere en producción.

§ 03

La estructura más básica es el array, o lista: una secuencia ordenada de elementos. Saber exactamente en qué es rápido y en qué es lento fija la base para todo lo demás.

Array — una secuencia ordenada y numerada

Una fila de casilleros numerados: los elementos están en orden y cada uno tiene una posición — casillero 0, casillero 1, casillero 2 — así que puedes ir directo a cualquiera por su número.

Un array (o list) guarda los elementos en orden, cada uno en una posición numerada llamada index, que empieza en 0. Como los elementos están en una disposición conocida y contigua, saltar a cualquier posición por su index es instantáneo — O(1). Los arrays son la opción por defecto para «un montón de cosas en orden», y el acceso directo por posición es su superpoder.

Hay un precio. Añadir o quitar al final es barato. Pero insertar o borrar en el medio desplaza todo lo que viene después para mantener intactos el orden y la numeración — O(n).

ann0bob1cid2dan3eve4fay5gus6hal7a[5] → straight there · O(1)index (position), starts at 0
Conoces el index — abres el casillero correcto de inmediato.
newannbobciddanevefayinsert in the middle → everything after shifts · O(n)newappend at the end · cheap
Insertar en el medio desplaza a todos los siguientes; añadir al final es barato.
StructureArray· list, index
Qué es
Elementos en orden, cada uno con un index numerado desde cero.
Rápido
Acceso por index — O(1); añadir al final — barato.
Lento
Buscar por valor — O(n); insertar o borrar en el medio — O(n).
Ejemplo

Un feed de publicaciones que se lee en orden y al que se añade al final.

Cuándo usarlo
Lees por posición y sobre todo añades al final.
Relaciones

Su punto débil — buscar por valor — lo arregla un Hash Map; Stack y Queue suelen construirse sobre él.

Linear search — encontrar por valor

Puedes abrir el casillero 500 al instante — pero si solo sabes qué hay dentro y no en qué casillero, tienes que abrirlos uno por uno hasta encontrarlo.

La trampa: un array es rápido solo cuando conoces el index. Para encontrar un elemento por su contenido — «¿está este email en la lista?» — tienes que revisar cada uno por turno. Eso es la linear search, O(n): lenta en listas grandes. Ese hueco es justo el problema que resuelve la siguiente estructura.

Is "fay" in the list?ann✗bob✗cid✗dan✗eve✗fay✓gushalcheck one by one → O(n)
Sin index miramos uno por uno — en el peor caso, toda la lista.
TermLinear search· scan
Qué es
Revisar los elementos uno por uno hasta encontrar el que quieres.
Coste
O(n): diez veces más datos — diez veces más tiempo.
Ejemplo
emails.includes(x) en una lista de un millón de direcciones.
Ojo
Dentro de otro bucle se vuelve O(n²) — el clásico «lento en producción».
Relaciones
Se sustituye por una búsqueda O(1) en un Hash Map o Set.

Un array es una secuencia ordenada e indexada: acceso instantáneo por posición, pero O(n) para buscar por valor o insertar en el medio.

§ 04

Si una estructura merece ser tu caballo de batalla por defecto, es el hash map. Resuelve la mayor debilidad del array — encontrar cosas por valor — y lo hace casi al instante.

Hash Map — pares clave-valor

Una guía telefónica: buscas a una persona por su nombre y obtienes su número al instante. No recorres todas las entradas — el nombre te lleva directo a la respuesta.

Un hash map (también llamado diccionario, hash table o simplemente map) guarda los datos como pares clave-valor: le das una clave y te devuelve el valor correspondiente. Un usuario por ID, un ajuste por nombre, un conteo por palabra — directamente, por la clave. Donde un array te obliga a conocer la posición, un hash map te deja encontrar por un nombre con sentido.

keyvalue"ann"+598 91 111"bob"+598 92 222"eve"+598 93 333get("eve") → "+598 93 333" — no scanning
La clave lleva directo al valor — sin mirar las demás entradas.
StructureHash Map· diccionario, hash table, map
Qué es
Pares clave → valor con búsqueda por clave.
Rápido
Buscar, insertar y borrar por clave — en la práctica O(1).
Lento

Sin orden; encontrar «por valor» en lugar de por clave vuelve a ser un recorrido.

Ejemplo

users[id], settings["theme"], conteo de palabras counts[word] += 1.

Cuándo usarlo
Buscas constantemente por un identificador.
Relaciones

Su velocidad viene de la Hash function; sin valores se convierte en un Set.

Hash function — por qué la búsqueda es instantánea

Un archivador mágico que, dada una etiqueta, abre directo el cajón correcto sin revisar los demás — el número de cajones no lo hace más lento.

La magia de un hash map es que buscar por clave es en la práctica O(1) — tiempo constante, sin importar cuántos elementos contenga. La clave pasa por una hash function que calcula dónde vive el valor, así que el map salta directo allí en lugar de buscar. Un millón de entradas o diez, encontrar una es igual de rápido. Por eso el hash map es el caballo de batalla: «encontrar por nombre» es lo que los programas hacen constantemente.

"eve"keyhash(key)→ slot 3012"eve" → +598 93 33334567computes where the value lives→ jumps there, no search
La hash function convierte una clave en un número de casilla — el map va directo allí.
TermHash function· hashing
Qué es

Una función que calcula, a partir de una clave, dónde está su valor en la tabla.

Cómo funciona

La misma clave siempre da la misma casilla — así que la búsqueda nunca recorre las entradas.

Ejemplo
hash("eve") → casilla 3 → ahí está el número de Eve.
Relaciones
El corazón de Hash Map y Set.

Set — presente o no, sin valores

Una lista de invitados en la puerta — no necesitas ningún detalle, solo un sí o un no: ¿está este nombre en la lista? Se comprueba al instante, sin recorrer nada.

Un primo cercano es el set: un hash map que guarda solo claves, sin valores, para responder rápido una pregunta — «¿está presente esto?». Comprobar pertenencia y evitar duplicados son ambos O(1). Cada vez que te veas recorriendo una lista para preguntar «¿ya vi esto?», un set convierte esa lenta comprobación O(n) en una instantánea.

has("eve")?add("bob")Setannbobeveyes · O(1)already thereno duplicate
Un set responde sí o no en O(1) y nunca guarda duplicados.
StructureSet· membership
Qué es
Una colección de claves únicas sin valores.
Rápido

«¿Está aquí?» y añadir — O(1); los duplicados se descartan automáticamente.

Ejemplo

seen = set() — saltarse los emails ya enviados; quitar los repetidos de una lista.

Cuándo usarlo
Unicidad y comprobaciones rápidas de pertenencia.
Relaciones
Un Hash Map sin los valores.

Un hash map encuentra un valor por su clave en O(1) efectivo — el caballo de batalla para buscar por identificador. Su primo el set responde «¿está presente?» igual de rápido.

§ 05

A veces el orden en que sacas las cosas importa tanto como lo que guardas. Dos estructuras formalizan los dos órdenes naturales — y la diferencia entre ellas es una sola regla intuitiva.

Stack — último en entrar, primero en salir (LIFO)

Una pila de platos: pones encima y tomas de encima, así que el último plato que dejaste es el primero que recoges.

Un stack sigue LIFO — last in, first out. Añades (push) y quitas (pop) por el mismo extremo, así que el elemento más reciente sale primero. Encaja con todo lo que se anida o se deshace en orden inverso: un historial de deshacer, el botón de atrás, la call stack de un programa. Ambas operaciones son O(1).

page 1page 2page 3page 4← top (newest)pushpoplast in, first out
Push pone arriba, pop toma de arriba: el más nuevo sale primero.
StructureStack· LIFO
Qué es
Añadir y quitar solo por arriba.
Rápido
push y pop — O(1).
Ejemplo

Deshacer en un editor, el botón de atrás del navegador, la call stack.

Cuándo usarlo
Necesitas «lo más reciente primero» o «deshacer lo último».
Relaciones
Espejo de Queue: los mismos datos, el otro extremo para sacar.

Queue — primero en entrar, primero en salir (FIFO)

Una cola en una taquilla: se atiende a la gente en el orden en que llegó, los recién llegados se ponen al final y se atiende al primero de la fila.

Una queue sigue FIFO — first in, first out. Añades por detrás (enqueue) y quitas por delante (dequeue), así que los elementos se procesan en orden de llegada. Es la estructura para la equidad y el orden: tareas por procesar, trabajos en espera, peticiones que atender por turno — justo la idea de la cola de mensajes del curso de queues. Como un stack, sus operaciones son O(1).

job 1job 2job 3job 4dequeueenqueuefront (oldest)back (newest)first in, first out
Los recién llegados se ponen al final, se atiende al primero — por orden de llegada.
StructureQueue· FIFO
Qué es
Añadir por detrás, tomar por delante.
Rápido
enqueue y dequeue — O(1).
Ejemplo

Trabajos para workers en segundo plano, peticiones atendidas por turno.

Cuándo usarlo
El orden de llegada debe ser el orden de procesamiento.
Relaciones

Espejo de Stack; a gran escala crece hasta ser una cola de mensajes.

La regla determina el comportamiento

El mismo montón de trabajo, dos puertas: una devuelve el elemento más reciente, la otra el más antiguo. La única elección de qué extremo cambia todo lo que viene después.

Los stacks y las queues guardan el mismo tipo de datos; la única diferencia es por qué extremo quitas. Elegir entre ellos es elegir el orden en que vuelve tu trabajo: inverso y anidado (stack) o justo y secuencial (queue). Una decisión pequeña con un efecto grande — acierta con el orden y el resto de la lógica encaja sola.

in: 1, 2, 3same itemsStacktake from topQueuetake from frontout: 3, 2, 1newest firstout: 1, 2, 3arrival order
Metes 1, 2, 3: un stack devuelve 3, 2, 1; una queue devuelve 1, 2, 3.

Un stack es último-en-entrar-primero-en-salir — deshacer, anidar, invertir. Una queue es primero-en-entrar-primero-en-salir — procesamiento justo y en orden. Mismos datos; el extremo por el que quitas es toda la diferencia.

§ 06

Las últimas estructuras manejan datos que no son una línea plana sino que tienen forma — cosas que se ramifican en jerarquías o se conectan en redes. Así se modelan las relaciones.

Tree — una jerarquía

Un árbol genealógico o el organigrama de una empresa: una cosa arriba, que se ramifica hacia abajo en hijos, cada uno de los cuales puede ramificarse más — una estructura que se abre en abanico y nunca vuelve atrás.

Un tree organiza los datos como una jerarquía: una raíz (root) arriba, que se ramifica en nodos que tienen hijos, y así hacia abajo. Modela todo lo anidado — carpetas dentro de carpetas, comentarios y sus respuestas, un menú de categorías. La forma ramificada refleja el anidamiento del mundo real, lo que hace de los trees el ajuste natural siempre que tus datos son «cosas dentro de cosas». La mayoría de las jerarquías que encuentras en el software son trees por debajo.

/ (root)docssrccv.pdfnotesapp.tslibnode with children· no loops back
Un sistema de archivos es un tree: una raíz, carpetas como nodos, archivos como hojas, sin ciclos.
StructureTree· root, node
Qué es
Una jerarquía: cada nodo puede tener hijos, pero nada vuelve atrás.
Ejemplo

Carpetas y archivos, un hilo de comentarios, el árbol de categorías de una tienda.

Cuándo usarlo
Tus datos son «cosas dentro de cosas».
Ojo

Si aprietas una jerarquía en una lista plana, tendrás que volver a pegarla a mano.

Relaciones

Un tree ordenado y parejo es un Balanced tree; un tree es un caso particular de Graph.

Balanced tree — búsqueda en O(log n)

Encontrar un nombre en una guía telefónica abriendo por la mitad, luego por la mitad de la mitad derecha, una y otra vez — cada paso descarta la mitad de lo que queda.

Un tree bien organizado, equilibrado, da una propiedad potente: puedes buscar en él en O(log n) dividiendo el espacio a la mitad una y otra vez, como encuentras una palabra en un diccionario sin leer cada página. Esa forma logarítmica apenas crece aunque los datos exploten — mil millones de elementos son solo unos treinta pasos. Así mantienen las bases de datos las búsquedas rápidas a escala enorme: datos ordenados en forma de tree, buscados por mitades.

50257512376288find 6262 > 50 → right62 < 75 → lefteach step drops half · 1 billion items ≈ 30 steps · O(log n)
Buscando 62: mayor que 50 — a la derecha, menor que 75 — a la izquierda. Cada paso descarta la mitad.
StructureBalanced tree· balanced search tree
Qué es
Un tree ordenado con la misma profundidad por todos lados.
Cómo funciona

En cada nodo se compara y se entra en una mitad — la otra mitad no se vuelve a mirar.

Rápido
Búsqueda — O(log n): mil millones de elementos ≈ 30 pasos.
Ejemplo
Índices de bases de datos: claves ordenadas en forma de tree.
Relaciones

Un Tree especial; a diferencia de un Hash Map, conserva el orden.

Graph — una red de conexiones

Un mapa de ciudades unidas por carreteras, o de personas unidas por amistades — cosas conectadas entre sí en cualquier patrón, sin arriba ni abajo.

Un graph es la forma más general: nodos conectados por aristas (edges), en cualquier patrón, incluidos los ciclos. Modela redes — conexiones sociales, carreteras entre ciudades, enlaces entre páginas, dependencias entre tareas. Siempre que los datos sean en el fondo «cosas relacionadas con otras cosas» y no una jerarquía ni una línea, es un graph. Muchos problemas difíciles e interesantes — la ruta más corta, quién está conectado con quién — son problemas de graphs en el fondo.

AnnBobEveMaxKimLeaedgenodes + edges · any pattern · loops allowed (Bob–Kim–Eve)
Nodos y aristas en cualquier patrón; se permiten ciclos — a diferencia de un tree.
StructureGraph· node, edge
Qué es

Nodos y las aristas entre ellos — sin jerarquía, con ciclos permitidos.

Ejemplo

Amigos en una red social, carreteras entre ciudades, enlaces entre páginas, dependencias entre tareas.

Problemas típicos
La ruta más corta; quién está conectado con quién.
Cuándo usarlo
Los datos son una red, no una línea ni una jerarquía.
Relaciones
Un Tree es un graph con una raíz y sin ciclos.

Un tree modela jerarquía y, equilibrado, busca en O(log n) por mitades. Un graph modela una red de conexiones. Úsalos cuando los datos tengan forma — anidada o enlazada.

§ 07

Rara vez las construyes desde cero — tu lenguaje las trae. La habilidad está en elegir la correcta para el trabajo, y saber suficiente Big-O para notar una mala elección antes de que te muerda.

Dominant operation — elige por lo que más haces

Abasteces la cocina según lo que cocinas cada noche, no según lo que luce impresionante.

La decisión práctica casi siempre es: ¿qué operación haré más, y qué estructura vuelve rápida esa? ¿Buscar por clave, constantemente? Hash Map. ¿Necesitas las cosas en orden de llegada? Queue. ¿Sobre todo lees por posición? Array. Deja que la dominant operation elija la estructura, y acepta que será más lenta en lo que rara vez haces. Optimiza el caso común; la estructura es el cómo.

What do Ido most often?look up by keyHash mapis it present? dedupeSetread by position, appendArraynewest first, undoStackin arrival orderQueuethings inside thingsTreethings linked to thingsGraph
Nombra tu operación más frecuente — ella apunta a la estructura.
PracticeDominant operation· optimizar el caso común
Idea
La operación más frecuente elige la estructura, no la costumbre.
Ejemplo

Miles de búsquedas de usuario por ID por segundo → Hash Map, aunque se pierda el orden.

Coste

Las operaciones raras se vuelven más lentas — una compensación deliberada.

Relaciones
Trade-off aplicado en la práctica.

Map before loop — usa un map antes que un bucle

Antes de buscar a alguien entre la multitud cara por cara, compruebas si hay una lista de invitados — la lista responde al instante lo que la búsqueda hace despacio.

Un movimiento muy común y muy eficaz: cuando te descubras recorriendo una lista para encontrar o emparejar cosas — un bucle O(n), o peor, un bucle O(n²) dentro de otro bucle — pregúntate si un hash map o un set podría volverlo instantáneo. Cambiar una búsqueda anidada por una consulta a un map es una de las aceleraciones más frecuentes en el mundo real. La solución suele ser la estructura, no un bucle más rápido.

before: loop inside a loopfor a in orders1 000 itemsfor u in usersscan all · 1 000O(n²)1 000 000 checksafter: build a map once, then look upbyId = map(users)once · 1 000byId[a.userId]O(1) eachO(n)~2 000 steps
Antes: un bucle dentro de otro, un millón de comprobaciones. Después: construyes el map una vez y luego O(1) por búsqueda.
PracticeMap before loop· búsqueda en lugar de recorrido anidado
Problema
Por cada elemento recorremos otra lista — O(n²), lento en producción.
Idea
Construye un Hash Map o Set una vez y luego busca en él en O(1).
Ejemplo

En lugar de users.find(u => u.id === order.userId) dentro de un bucle sobre pedidos — construye antes byId y usa byId[order.userId].

Coste
Un poco de memoria para el map.
Relaciones
Convierte una Linear search dentro de un bucle en O(1).
Antes de elegir una estructura
  • Qué operación domina — ¿búsqueda, orden, añadir/quitar?
  • ¿Búsqueda por clave? Un Hash Map (o un Set, para presencia) es O(1).
  • ¿Acceso por posición, con muchos añadidos? Encaja un Array.
  • Importa el orden de salida — ¿lo más reciente (Stack) o lo más antiguo (Queue)?
  • Datos anidados o en red — ¿un Tree o un Graph?
  • A escala, ¿cuál es el Big-O — y ¿hay algo que sea O(n²) en secreto?
Señales de que eliges bien
  • Eliges la estructura por la operación que más haces, no por costumbre.
  • Recurres a un Hash Map o Set en lugar de recorrer una lista para encontrar o deduplicar.
  • Puedes nombrar el Big-O de tu camino crítico y no tienes ningún O(n²) oculto.
  • Usas un Stack o Queue cuando importa el orden de salida, y un Tree o Graph cuando los datos tienen forma.
  • Las cosas siguen rápidas al crecer los datos, porque elegiste la forma antes de que la escala la dejara al descubierto.

Cómo se conecta todo

Un árbol genealógico de herramientas: cada una cubre una debilidad de la anterior.

Big-O es la regla con que se mide cada estructura. Un Hash Map arregla el punto débil del Array (encontrar por valor); un Set es un Hash Map sin valores. Stack y Queue son una secuencia con la regla «tomar solo por un extremo». Un Tree añade jerarquía, y uno equilibrado busca en O(log n); un Graph levanta la última restricción y permite cualquier enlace.

Big-Omeasures every opArrayby indexHash mapby keySetpresenceStack / Queueorder ruleTreebalanced: log nGraphany linksfind fastkeys onlytake only from an endallow loops
Big-O las mide todas; cada estructura responde a una debilidad o a un límite de su vecina.

Chuleta: los 16 conceptos

Fundamentos

Data Structurecómo se disponen los datos

Una manera de organizar los datos para que tus operaciones comunes sean rápidas.

Trade-offno hay almuerzo gratis

La fortaleza en una operación cuesta debilidad en otra.

Big-O

Big-O notationcomplejidad asintótica

Cómo crece el trabajo al crecer el tamaño de datos n.

Complexity classesO(1), O(log n), O(n), O(n²)

Constante, logarítmica, lineal, cuadrática. O(n²) es una alarma.

Array

Arraylist

En orden, con index: O(1) por posición, O(n) para insertar en el medio.

Linear searchscan

Encontrar por valor revisando uno por uno. O(n).

Hash map

Hash Mapdiccionario, map

Clave → valor, búsqueda por clave en O(1) efectivo. Sin orden.

Hash functionhashing

Calcula a partir de la clave dónde vive el valor — así no hay recorrido.

Setmembership

Solo claves: «¿está aquí?» en O(1), sin duplicados.

Orden

StackLIFO

Último en entrar, primero en salir. Deshacer, botón de atrás, call stack.

QueueFIFO

Primero en entrar, primero en salir. Procesamiento en orden de llegada.

Forma

Treejerarquía

Raíz, nodos, hijos, sin ciclos.

Balanced treebalanced search tree

Búsqueda por mitades — O(log n). Cómo funcionan los índices de las bases de datos.

Graphred

Nodos y aristas en cualquier patrón. Redes, rutas, dependencias.

Cómo elegir

Dominant operationcaso común

La operación más frecuente elige la estructura.

Map before loopbúsqueda en vez de recorrido

Antes de un recorrido anidado — construye un Hash Map o Set.

No las construyes desde cero — las eliges. Haz coincidir la estructura con la operación que más haces, usa un map antes que un bucle y deja que Big-O te avise antes que la escala.

Fin del curso exprés · 7 capítulos · 16 conceptos

Ahora toca la práctica: busca un punto de tu código donde recorras una lista para encontrar o emparejar algo, y sustitúyelo por una búsqueda en un hash map o set — luego fíjate en cuánto más rápido va con datos grandes. Después, para una operación lenta, calcula su Big-O y pregúntate si otra estructura cambia la forma. Pero quédate con una idea por encima de las demás: la forma correcta vuelve fácil lo difícil. La mayoría de los «¿por qué esto es lento?» en realidad son «está en la estructura equivocada» — y elegir la correcta es la velocidad más barata que comprarás jamás.