🚀 Plan Maestro de Maestría Algorítmica y Arquitectura de Memoria (70 Días / 10 Semanas: Rust & Python)#
Objetivo de Alto Rendimiento: Desarrollar conexiones neuronales profundas, comprensión física y matemática de las estructuras de datos, y alcanzar autonomía técnica (seniority L5/L6+) para resolver problemas Easy, Medium y Hard de LeetCode y diseñar sistemas de baja latencia en Rust y Python sin depender de la IA ni de memorizaciones superficiales.
🧭 Índice Rápido del Repositorio (Navegador General)#
- 📖 Glosario Maestro de Conceptos (Raíz) y Glosario Maestro (Carpeta glossary): Enciclopedia técnica visual con 106 conceptos desglosados en 4 capas cognitivas (Intuición, Técnica, Código Rust/Python y Error Típico).
- 📊 Suite Visual de Arquitectura de Memoria y Algoritmos: 80 diagramas vectoriales SVG (10 panorámicas de arquitectura y 70 diagramas de sesión diaria) con diccionario visual de hardware.
- 🧪 Suite de 141 Pruebas Unitarias: Suite automatizada que cubre el 100% de los algoritmos y estructuras de datos de todo el programa.
- 💻 Módulos de Código en Python: Implementaciones de referencia limpias, modulares y tipadas de los 70 días.
- 📚 Sesiones de Estudio Diario en Markdown: Las 70 lecciones estructuradas con el protocolo Paper-First y trazas de hardware.
⚡ Acceso Directo por Semanas:#
- 0. Guía de Supervivencia desde Cero para Junior / Trainee: De Python a Rust Visual
- Preguntas de Autodiagnóstico Inicial para Junior / Trainee
- Semana 1: Búsqueda Binaria, Big O y Arreglos/Strings (Días 01 al 07)
- Semana 2: Memoria, Recursión y Listas Enlazadas (Días 08 al 14)
- Semana 3: Quicksort, Hash Tables, Stacks & Queues y Pila Monótona (Días 15 al 21)
- Semana 4: Árboles, BST, Grafos, TopoSort y Dijkstra (Días 22 al 28)
- Semana 5: Síntesis Compuesta, Heaps y Simulacro FAANG (Días 29 al 35)
- Semana 6: Greedy, Backtracking y Programación Dinámica (Días 36 al 42)
- Semana 7: Bits, Búsqueda Avanzada, Tries y DSU (Días 43 al 49)
- Semana 8: Trapping Rain Water, Fenwick/Segment Trees y LFU Cache (Días 50 al 56)
- Semana 9: KNN, Bloom Filters, HLL, Simhash, Knuth y Consistent Hashing (Días 57 al 63)
- Semana 10: Tests Diagnósticos, Gran Simulacro Staff y Graduación L6 (Días 64 al 70)
0. Guía de Supervivencia desde Cero para Junior / Trainee: De Python a Rust Visual#
🎨 Cómo Interpretar los Diagramas Visuales SVG y Trazas de Memoria#
Cada lección del programa incluye un diagrama arquitectónico en diagrams/sesiones/ diseñado bajo principios de codificación cognitiva. Para leerlos con la precisión de un ingeniero de sistemas:
- El Stack (Cajas Sólidas a la Izquierda): Representa la memoria fija de ejecución directa de la CPU. Observarás descriptores con tres campos de 8 bytes para
Vec<T>:ptr(dirección hexadecimal hacia el Heap),len(elementos activos) ycap(capacidad total asignada). - El Heap (Búferes Horizontales a la Derecha): Muestra bloques de celdas contiguas con sus direcciones físicas (
0x5000: [10 | 20 | 30 | _ ]). Las celdas con números contienen datos vivos; las celdas con_representan capacidad reservada pero no inicializada. - Fat Pointers (
&[T]y&str, Cajas Moradas de 16 Bytes): Observa cómo una referencia de slice no copia ningún dato: simplemente almacena un puntero al inicio del segmento deseado y la longitud visible. ¡Tiempo O(1) y 0 bytes de Heap! - Diferenciación de Flechas:
- Flecha sólida continua: Puntero dueño exclusivo (Ownership, por ejemplo un
Box<Node>oVec<T>). Si el origen desaparece, el destino se destruye. - Flecha punteada: Referencia prestada (Borrowing&T). El dueño reside en otra parte; esta flecha solo observa o muta temporalmente sin poder destruir la memoria.
🛡️ Las 5 Reglas de Oro de Rust para Algoritmos (Que Todo Junior Debe Saber el Día 1)#
1. Índices usize sin signo y la trampa del underflow en Búsqueda Binaria#
En Rust, los índices de arreglos tienen obligatoriamente el tipo usize (entero sin signo de 64 bits en x86_64). Como nunca puede ser negativo:
- Si calculas
let mut high = arr.len() - 1;con un arreglo vacío (len == 0),0usize - 1desborda a 18,446,744,073,709,551,615 provocando un pánico en depuración. - Si en búsqueda binaria calculas
high = mid - 1;cuandomid == 0, ocurre exactamente el mismo pánico. - La solución canónica y elegante: Trabajar con intervalos semiabiertos [low, high) donde
high = arr.len()y cuando se busca a la izquierda se hacehigh = mid;(¡cero restas a cero!). O bien utilizar el método seguromid.checked_sub(1).
2. Slices &[i32] y &mut [i32] en lugar de clonar Vec<i32>#
En Python, hacer arr[1:4] clona los datos en el Heap en O(K). Muchos programadores novatos en Rust escriben fn solve(arr: Vec<i32>) y clonan con .clone() para calmar al compilador.
- Clonar un vector de N elementos en cada nivel de recursión degrada un algoritmo de O(N) a un desastre de O(N²) en tiempo y memoria.
- La regla de oro: Pasa siempre referencias prestadas
&[i32](para lectura) o&mut [i32](para mutación in-place). Pesa solo 16 bytes en el Stack y tiene costo O(1) absoluto.
3. Option<usize> (Some(idx) / None) en lugar del número mágico -1#
En Python o C, las funciones de búsqueda suelen retornar -1 cuando un elemento no existe.
- En Rust, como los índices son
usize,-1no existe conceptualmente. Si intentas retornar-1i32y convertirlo ausize, obtendrás un índice astronómico que violará los límites de memoria. - Rust modela la ausencia de valor con el enum algebraico
Option<usize>(Some(index)si fue encontrado,Nonesi no existe). El compilador te obliga a desarmar elOptionconmatchoif let Some, erradicando fallos en producción.
4. HashMap::entry(), VecDeque y BinaryHeap con std::cmp::Reverse#
- Mapas de Frecuencia: En lugar de consultar
if map.contains_key(...)y luego insertar (dos búsquedas lentas), usa la API de un solo paso:*map.entry(x).or_insert(0) += 1;. - Colas FIFO: Jamás uses
vec.remove(0)(O(N)). UsaVecDeque::new()conpush_backypop_fronten O(1) estricto amortizado. - Min-Heap vs Max-Heap: En Python,
heapqes un Min-Heap por defecto. En Rust,BinaryHeapes un Max-Heap por defecto. Para obtener un Min-Heap en Rust, envuelve los valores enstd::cmp::Reverse(val).
5. Listas y Árboles con Option<Box<Node>> o Arena Indexing (Vec<Node>)#
En Rust no existen punteros nulos crudos (NULL).
- Para estructuras jerárquicas simples (árboles binarios o listas simples), se utiliza
Option<Box<Node>>donde cada nodo es el dueño único de sus descendientes. - Para grafos complejos o estructuras con punteros dobles y ciclos, la solución suprema de la industria no es usar punteros complicados (
Rc<RefCell<Node>>), sino el Arena Indexing: almacenar todos los nodos en unVec<Node>contiguo y usar enterosusizecomo identificadores. Esto maximiza la memoria caché L1 y simplifica el Borrow Checker al 100%.
🧪 Starter Code Inicial Compilable y Verificado (rustc --test)#
El siguiente código fuente en Rust demuestra en acción las 5 Reglas de Oro. Puedes compilarlo y ejecutarlo directamente con el compilador oficial de Rust:
use std::collections::{HashMap, VecDeque, BinaryHeap};
use std::cmp::Reverse;
// Regla 1 y 3: Búsqueda binaria segura con intervalos semiabiertos [low, high) y Option<usize>
pub fn safe_binary_search(nums: &[i32], target: i32) -> Option<usize> {
if nums.is_empty() {
return None;
}
let mut low: usize = 0;
let mut high: usize = nums.len(); // Half-open interval prevents underflow!
while low < high {
let mid = low + (high - low) / 2; // Prevents integer overflow
if nums[mid] == target {
return Some(mid); // Found!
} else if nums[mid] < target {
low = mid + 1;
} else {
high = mid; // Safe! No `mid - 1` underflow when mid == 0
}
}
None
}
// Regla 2: Inversión in-place sobre un mutable slice &mut [i32] sin clonar memoria
pub fn reverse_slice(arr: &mut [i32]) {
if arr.is_empty() { return; }
let mut left = 0;
let mut right = arr.len() - 1;
while left < right {
arr.swap(left, right);
left += 1;
right = right.saturating_sub(1);
}
}
// Regla 4: Conteo de frecuencias en 1 sola búsqueda con entry().or_insert()
pub fn frequency_map(items: &[i32]) -> HashMap<i32, usize> {
let mut map = HashMap::new();
for &x in items {
*map.entry(x).or_insert(0) += 1; // Single hash lookup!
}
map
}
// Regla 4: Cola FIFO O(1) con VecDeque
pub fn bfs_level_order_simulation(root_val: i32) -> Vec<i32> {
let mut queue = VecDeque::new();
let mut visited = Vec::new();
queue.push_back(root_val);
while let Some(current) = queue.pop_front() { // O(1) front extraction
visited.push(current);
if current < 3 {
queue.push_back(current + 1);
}
}
visited
}
// Regla 4: Min-Heap en Rust usando Reverse(T)
pub fn min_heap_k_smallest(nums: &[i32], k: usize) -> Vec<i32> {
let mut min_heap = BinaryHeap::new();
for &x in nums {
min_heap.push(Reverse(x)); // Reverse converts Max-Heap into Min-Heap
}
let mut result = Vec::new();
for _ in 0..k.min(nums.len()) {
if let Some(Reverse(val)) = min_heap.pop() {
result.push(val);
}
}
result
}
// Regla 5: Arena Indexing para Árboles y Grafos continuos en memoria
#[derive(Debug, Clone)]
pub struct ArenaTreeNode {
pub val: i32,
pub left: Option<usize>, // Index into arena vector
pub right: Option<usize>, // Index into arena vector
}
pub struct ArenaTree {
pub nodes: Vec<ArenaTreeNode>, // Contiguous buffer in Heap
}
impl ArenaTree {
pub fn new() -> Self {
Self { nodes: Vec::new() }
}
pub fn add_node(&mut self, val: i32) -> usize {
let idx = self.nodes.len();
self.nodes.push(ArenaTreeNode { val, left: None, right: None });
idx
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_binary_search_found_and_not_found() {
let data = [10, 20, 30, 40, 50];
assert_eq!(safe_binary_search(&data, 30), Some(2));
assert_eq!(safe_binary_search(&data, 10), Some(0));
assert_eq!(safe_binary_search(&data, 50), Some(4));
assert_eq!(safe_binary_search(&data, 99), None);
assert_eq!(safe_binary_search(&[], 5), None);
}
#[test]
fn test_reverse_slice() {
let mut data = [1, 2, 3, 4, 5];
reverse_slice(&mut data);
assert_eq!(data, [5, 4, 3, 2, 1]);
}
#[test]
fn test_frequency_map() {
let nums = [4, 2, 4, 1, 2, 4];
let freq = frequency_map(&nums);
assert_eq!(freq.get(&4), Some(&3));
assert_eq!(freq.get(&2), Some(&2));
assert_eq!(freq.get(&1), Some(&1));
}
#[test]
fn test_vec_deque_bfs() {
let visited = bfs_level_order_simulation(1);
assert_eq!(visited, vec![1, 2, 3]);
}
#[test]
fn test_min_heap() {
let nums = [40, 10, 30, 20, 50];
let smallest3 = min_heap_k_smallest(&nums, 3);
assert_eq!(smallest3, vec![10, 20, 30]);
}
#[test]
fn test_arena_tree() {
let mut tree = ArenaTree::new();
let root = tree.add_node(100);
let left = tree.add_node(50);
let right = tree.add_node(150);
tree.nodes[root].left = Some(left);
tree.nodes[root].right = Some(right);
assert_eq!(tree.nodes[root].val, 100);
assert_eq!(tree.nodes[tree.nodes[root].left.unwrap()].val, 50);
assert_eq!(tree.nodes[tree.nodes[root].right.unwrap()].val, 150);
}
}
# Para ejecutar las pruebas en tu consola local:
rustc --test starter_algorithms.rs -o starter_test.exe
.\starter_test.exe
❓ Preguntas de Autodiagnóstico Inicial para Junior / Trainee#
Antes de iniciar tu estudio diario, responde honestamente a estas 5 preguntas diagnósticas para evaluar la solidez de tus modelos mentales:
🔍 Pregunta 1: Anatomía de Memoria y Slicing (Python vs Rust)
Enunciado: Dado un arreglo de 100,000 números enteros, una función recursiva divide el arreglo a la mitad en cada paso ejecutando un slice de la forma left_half = arr[0:mid].
- ¿Qué ocurre exactamente en la memoria física RAM (Stack y Heap) en Python?
- ¿Qué ocurre en Rust si utilizas un slice prestado
let left_half = &arr[0..mid];? - ¿Cómo impacta esto en la complejidad espacial auxiliar global si la recursión tiene una profundidad de log₂ N?
Respuesta Paso a Paso:
- En Python: Cada operación de slice
arr[0:mid]solicita al asignador del sistema operativo un nuevo bloque contiguo en el Heap y copia físicamente los punteros de los elementos. En cada uno de los log N niveles del árbol recursivo, la suma de los tamaños de las sublistas clonadas es igual a N. Por lo tanto, el slicing en Python consume Θ(N log N) de memoria física auxiliar acumulada en el Heap. - En Rust: La expresión
&arr[0..mid]no realiza ninguna reserva de memoria en el Heap. Crea únicamente un Fat Pointer de 16 bytes en el marco de pila (Stack Frame) de la función (8 bytes con el puntero base*const i32y 8 bytes con la longitudlen). - Impacto Asintótico: En Rust, el espacio auxiliar en el Heap es estrictamente O(1), y el espacio auxiliar total en el Call Stack es simplemente O(log N) por los marcos de llamada. Rust es entre 10 y 100 veces más rápido y consume órdenes de magnitud menos memoria RAM física.
🔍 Pregunta 2: Subdesbordamiento de Índices y Búsqueda Binaria en Rust
Enunciado: Un desarrollador novato escribe la siguiente búsqueda binaria en Rust:
let mut low: usize = 0;
let mut high: usize = arr.len() - 1; // Línea A
while low <= high { // Línea B
let mid = (low + high) / 2; // Línea C
if arr[mid] == target { return Some(mid); }
else if arr[mid] < target { low = mid + 1; }
else { high = mid - 1; } // Línea D
}
Identifica los tres errores críticos de bajo nivel en las líneas A, C y D y explica cómo corregirlos formalmente.
Respuesta Paso a Paso:
- Fallo en Línea A: Si
arres un slice vacío (len == 0),0usize - 1produce un *subdesbordamiento (underflow)*. En modo depuración el programa se detiene conpanic! 'attempt to subtract with overflow'. En modo release envuelve a 2⁶⁴-1, provocando un fallo de límites de memoria en la siguiente línea. - Fallo en Línea C: Si
low + highexcede el rango máximo del tipo entero (en arreglos gigantescos de más de 2 mil millones de elementos con enteros de 32 bits), la suma desborda produciendo un número negativo o erróneo. Se debe calcular siempre como:mid = low + (high - low) / 2;. - Fallo en Línea D: Si
targetes menor que el elemento en el índice 0,midvaldrá0. Ejecutarhigh = 0usize - 1detona un pánico inmediato de underflow en la CPU. - Corrección Canónica: Usar rangos semiabiertos [low, high):
``
rust let mut low = 0; let mut high = arr.len(); // Seguro con len == 0 while low < high { let mid = low + (high - low) / 2; if arr[mid] == target { return Some(mid); } else if arr[mid] < target { low = mid + 1; } else { high = mid; } // Seguro: nunca resta a 0 }``
🔍 Pregunta 3: Costo de Consultas Hash y Ataques de Colisión (HashDoS)
Enunciado:
- ¿Cuál es la diferencia de hardware entre hacer
if map.contains_key(&k) { map.insert(k, map[&k] + 1); }y hacer*map.entry(k).or_insert(0) += 1;? - ¿Por qué Rust utiliza el algoritmo criptográficamente resistente SipHash 1-3 por defecto en su
HashMapen lugar de un algoritmo más rápido como FNV o MurmurHash?
Respuesta Paso a Paso:
- Doble Consulta vs Entrada Única:
- El código ingenuo con
contains_keyejecuta tres búsquedas independientes en la tabla hash: calcula el hash y recorre la cubeta para verificar existencia; luego calcula el hash para leer el valor actual (map[&k]); y calcula el hash por tercera vez para reinsertar el nuevo valor. - La API idiomática.entry(k).or_insert(0)computa el hash una sola vez, localiza la celda de memoria en la cubeta y retorna una referencia mutable directa&mut Va los bytes de esa celda en el Heap, actualizando el contador in-place en un tercio de las instrucciones de CPU. - Protección contra HashDoS: Si una tabla hash utiliza una función hash predecible y lineal, un atacante remoto puede enviar miles de cadenas cuidadosamente diseñadas que produzcan exactamente el mismo valor hash módulo M. Todas las claves colisionan en la misma ranura, degradando la búsqueda de O(1) a O(N) y consumiendo el 100% de la CPU del servidor web. Rust usa SipHash con semillas aleatorias por proceso para hacer matemáticamente inviable la predicción de colisiones forzadas.
🔍 Pregunta 4: La Trampa del Min-Heap al migrar de Python a Rust
Enunciado: Un ingeniero migra el Algoritmo de Dijkstra de Python a Rust. En Python usaba heapq.heappush(pq, (dist, node)). En Rust crea un BinaryHeap::new() y hace pq.push((dist, node)).
- ¿Qué camino matemático encontrará el algoritmo de Rust y por qué?
- ¿Cómo se corrige utilizando la librería estándar de Rust sin multiplicar distancias por -1?
- ¿Por qué es obligatoria la verificación
if d > dist[u] { continue; }al extraer del heap?
Respuesta Paso a Paso:
- Max-Heap vs Min-Heap: Por diseño estándar,
BinaryHeapen Rust es un Max-Heap (extrae el elemento mayor primero). Si insertas distancias positivas, Dijkstra procesará primero los caminos más largos y costosos, rompiendo el invariante voraz y produciendo caminos subóptimos o incorrectos. - Corrección con
Reverse: Se envuelve la distancia o la tupla completa con el adaptadorstd::cmp::Reverse: ``rust pq.push((Reverse(dist), node)); // Al extraer: let (Reverse(d), u) = pq.pop().unwrap();`Reverseinvierte las comparaciones del traitOrd` en compilación con cero costo de CPU. - *Poda de Duplicados Perezosos (Lazy Deletion)*: En grafos, un mismo nodo u puede recibir múltiples actualizaciones de distancia más corta e insertarse varias veces en el heap. Cuando el heap finalmente extrae las versiones viejas con distancias peores, la condición
if d > dist[u] { continue; }las descarta en O(1) sin volver a relajar sus aristas vecinas, evitando que la complejidad se degrade hacia O(E · V).
🔍 Pregunta 5: Jerarquía de Memoria Caché de CPU, Listas Enlazadas y Arena Indexing
Enunciado: En teoría matemática asintótica, insertar un elemento en la cabeza de una lista enlazada es O(1), mientras que insertar en un vector dinámico es O(1) amortizado. Sin embargo, al iterar y procesar 1,000,000 de elementos, un vector contiguo en Rust o C++ es frecuentemente 50 veces más rápido que una lista enlazada.
- Explica este fenómeno desde primeros principios de hardware: líneas de caché L1/L2/L3, localidad espacial y cache misses.
- ¿Por qué la técnica de Arena Indexing (
Vec<Node>) es el estándar de oro para grafos y árboles en Rust frente a punterosRc<RefCell<Node>>?
Respuesta Paso a Paso:
- Líneas de Caché de Hardware y Localidad Espacial:
- Los microprocesadores modernos no leen bytes individuales de la memoria RAM: leen bloques contiguos de 64 bytes llamados líneas de caché (cache lines).
- En un
Vec<i32>, los enteros de 4 bytes están pegados uno al lado del otro. Cuando la CPU lee el elemento 0, el hardware carga automáticamente los siguientes 15 enteros contiguos en la memoria caché L1 ultrarrápida (latencia de ~1 nanosegundo). - En una lista enlazada, cada nodo fue asignado por separado en el Heap en momentos distintos. Sus direcciones están desparramadas por la RAM. Seguir cada punteronextrequiere esperar entre 50 y 100 nanosegundos a que la memoria RAM principal responda (Cache Miss). La CPU pasa el 90% de su tiempo ociosa esperando datos. - Ventajas del Arena Indexing:
- Agrupa todos los nodos del grafo en un único vector contiguo
Vec<Node>, recuperando la localidad de caché y la velocidad del silicio. - Reemplaza punteros pesados de 8 bytes por índices enterosusizeou32, reduciendo el consumo de memoria a la mitad. - Respeta de forma natural las reglas de Ownership de Rust: el vector es el único dueño de todos los nodos. No hay contadores de referencias atómicos (Rc), no hay chequeos de préstamos en runtime (RefCell), y no existen ciclos huérfanos que provoquen fugas de memoria.
🧠 La Metodología de Aprendizaje Funcional (Paper-First)#
Muchos desarrolladores caen en la "ilusión de competencia": leen una solución, la entienden superficialmente, le piden a la IA que genere el código, y creen que lo dominan. Cuando llega la entrevista técnica o la pizarra en blanco, la mente se queda bloqueada.
Para construir seniority real, este plan utiliza 4 métodos cognitivos basados en neurociencia:
- Protocolo Paper-First (Traza en Papel Obligatoria): - Antes de escribir una sola línea de código en el editor, debes ejecutar el algoritmo en papel. - Dibujarás la memoria, los índices y una tabla con el estado de cada variable en cada iteración. - Si no puedes simularlo a mano con lápiz en una lista de 5 elementos, no lo entiendes y la computadora solo ejecutará tus confusiones más rápido.
- Técnica de Feynman: - Cada lección te exige explicar el concepto fundamental con palabras cotidianas y modelos mecánicos (por ejemplo: la memoria RAM como casilleros numerados contiguos, el logaritmo como doblar una hoja de papel, el puntero como una cuerda hacia otra caja).
- Recuperación Activa (Active Recall): - Cada sesión incluye preguntas de verificación antes de mostrar la solución. Intenta responderlas mentalmente o por escrito antes de desplegar las respuestas.
- Repetición Espaciada (Spaced Repetition): - Al inicio de cada día repasarás 5 minutos los conceptos del día anterior. Al final de cada ciclo semanal tendrás un examen de consolidación global.
🗺️ Hoja de Ruta Completa de 70 Días / 10 Semanas (Grokking + CTCI + Knuth TAOCP + DP + Tries + DSU + BIT + Segment Trees + LFU + Consistent Hashing + Bloom Filters + Staff Mock)#
Semana 1: Fundamentos de Búsqueda, Complejidad y Arreglos/Strings (Días 01 al 07)#
| Día | Sesión Interactiva | Diagrama de Memoria | Libro / Módulo | Patrón Algorítmico Central | Puente LeetCode |
|---|---|---|---|---|---|
| 01 | Búsqueda Binaria, Invariantes y Logaritmos | 📊 Ver Diagrama | Grokking (Cap. 1, P1) | Divide & Conquer / Reducción a la mitad | LC 704 (Easy), LC 35 (Easy) |
| 02 | Big O: Complejidad Asintótica y Espacio | 📊 Ver Diagrama | Grokking (Cap. 1, P2) | Análisis asintótico y Marcos del Call Stack | Ejercicios analíticos en papel |
| 03 | Memoria RAM, Arreglos y Strings In-Place | 📊 Ver Diagrama | CTCI (Cap. 1, P1) | Is Unique: Bit Vector & URLify back-to-front | LC 344 (Easy), LC 217 (Easy) |
| 04 | Hash Maps y Conteo de Frecuencia | 📊 Ver Diagrama | CTCI (Cap. 1, P2) | Check Permutation & Palindrome Bit Toggle | LC 242 (Easy), LC 1 (Easy), LC 49 (Med) |
| 05 | Técnica de Dos Punteros Convergentes vs Lector/Escritor | 📊 Ver Diagrama | CTCI (Cap. 1, P3) | In-Place Array Mutation y Monotonicidad | LC 125 (Easy), LC 26 (Easy), LC 167 (Med) |
| 06 | Strings Avanzados, RLE y Rotaciones | 📊 Ver Diagrama | CTCI (Cap. 1, P4) | Invariantes de estado, RLE y Concatenación s₁+s₁ | LC 161 (Med), LC 443 (Med) |
| 07 | Matrices 2D y Consolidación Semana 1 | 📊 Ver Diagrama | CTCI (Cap. 1, P5) | Rotate Matrix 90° & Zero Matrix O(1) space | LC 48 (Med), LC 73 (Med) |
Semana 2: Memoria Dinámica, Recursión y Listas Enlazadas (Días 08 al 14)#
| Día | Sesión Interactiva | Diagrama de Memoria | Libro / Módulo | Patrón Algorítmico Central | Puente LeetCode |
|---|---|---|---|---|---|
| 08 | Memoria RAM: Arreglos vs Listas Enlazadas | 📊 Ver Diagrama | Grokking (Cap. 2) | Acceso O(1) vs O(N), Nodos Heap, Selection Sort | LC 206 (Easy), LC 912 (Med) |
| 09 | Recursión y Anatomía del Call Stack | 📊 Ver Diagrama | Grokking (Cap. 3) | Caso Base, Stack Frames, LIFO, Inversión Recursiva | LC 509 (Easy), LC 206 (Easy) |
| 10 | Técnica Runner y Detección de Duplicados | 📊 Ver Diagrama | CTCI (Cap. 2, P1) | Remove Dups con Buffer y Ventana de K pasos | LC 83 (Easy), LC 19 (Med) |
| 11 | Borrado Intermedio y Partición con Centinelas | 📊 Ver Diagrama | CTCI (Cap. 2, P2) | Mutación de Contenido in-place vs Dummy Nodes | LC 237 (Med), LC 86 (Med) |
| 12 | Suma de Listas Big/Little Endian y Palíndromos | 📊 Ver Diagrama | CTCI (Cap. 2, P3) | Aritmética arbitraria, Inversión de mitad O(1) | LC 2 (Med), LC 234 (Easy) |
| 13 | Intersección de Listas y Detección de Ciclos de Floyd | 📊 Ver Diagrama | CTCI (Cap. 2, P4) | Topología en "Y", Ecuación k=nC-m, Liebre y Tortuga | LC 160 (Easy), LC 141, LC 142 |
| 14 | Consolidación Global Semana 2 y Simulacro | 📊 Ver Diagrama | Consolidación | Los 5 Patrones de Oro de Listas Enlazadas | LC 21 (Easy), LC 143 (Med) |
Semana 3: Divide & Conquer, Hash Tables Avanzadas, Stacks & Queues y Monotonic Stack (Días 15 al 21)#
| Día | Sesión Interactiva | Diagrama de Memoria | Libro / Módulo | Patrón Algorítmico Central | Puente LeetCode |
|---|---|---|---|---|---|
| 15 | Divide y Vencerás, Quicksort y Quickselect | 📊 Ver Diagrama | Grokking (Cap. 4) | Invariante Lomuto, Caso promedio O(N log N), Quickselect | LC 912 (Med), LC 215 (Med) |
| 16 | Hash Tables Avanzadas: Linear Probing y Rehashing | 📊 Ver Diagrama | Grokking (Cap. 5) | Factor de carga lpha, Lápidas, SwissTable | LC 706 (Easy), LC 380 (Med) |
| 17 | Fundamentos de Stacks & Queues y Three in One | 📊 Ver Diagrama | CTCI (Cap. 3, P1) | LIFO vs FIFO en RAM, Particiones Fijas en 1 Array | LC 20 (Easy), LC 225 (Easy) |
| 18 | Stack Min O(1) y Pila de Platos (SetOfStacks) | 📊 Ver Diagrama | CTCI (Cap. 3, P2) | Pila Auxiliar de Mínimos con Conteo, Arrays de Pilas | LC 155 (Med), LC 1172 (Hard) |
| 19 | Cola mediante Pilas (Queue via Stacks) y Sort Stack | 📊 Ver Diagrama | CTCI (Cap. 3, P3) | Doble Inversión LIFO $ o$ FIFO, Transferencia Lazy | LC 232 (Easy), LC 225 (Easy) |
| 20 | Refugio de Animales (Animal Shelter) y FIFO Selectivo | 📊 Ver Diagrama | CTCI (Cap. 3, P4) | FIFO con Timestamps Duales, Sincronización O(1) | LC 981 (Med), Diseño OOP |
| 21 | Patrón Pila Monótona y Consolidación Semana 3 | 📊 Ver Diagrama | Consolidación | Next Greater Element O(N) amortizado, Línea de Visión | LC 739 (Med), LC 496, LC 503 |
Semana 4: Grafos, Árboles Binarios, BST, Orden Topológico y Dijkstra (Días 22 al 28)#
| Día | Sesión Interactiva | Diagrama de Memoria | Libro / Módulo | Patrón Algorítmico Central | Puente LeetCode |
|---|---|---|---|---|---|
| 22 | Grafos, Listas de Adyacencia y BFS | 📊 Ver Diagrama | Grokking (Cap. 6) | Cola FIFO, Set visited, Caminos mínimos en no ponderados | LC 1971 (Easy), LC 102 (Med) |
| 23 | Árboles Binarios, Recorridos y Minimal Tree | 📊 Ver Diagrama | CTCI (Cap. 4, P1) | Recorridos In/Pre/Post/Level, Bisección Divide & Conquer | LC 108 (Easy), LC 102 (Med) |
| 24 | Validación de BST y Comprobación de Balanceo | 📊 Ver Diagrama | CTCI (Cap. 4, P2) | Propagación de cotas (low, high), Post-order O(N) | LC 98 (Med), LC 110 (Easy) |
| 25 | Sucesor en BST y Ancestro Común Más Bajo (LCA) | 📊 Ver Diagrama | CTCI (Cap. 4, P3) | Topología de ancestros, Post-order divergente en árbol | LC 285 (Med), LC 236 (Med) |
| 26 | Orden Topológico y Algoritmo de Kahn | 📊 Ver Diagrama | CTCI (Cap. 4, P4) | In-degrees, DAG acíclico, Detección de ciclos dirigida | LC 207 (Med), LC 210 (Med) |
| 27 | Verificación de Subárboles y Paths with Sum | 📊 Ver Diagrama | CTCI (Cap. 4, P5) | Pre-order serialization, Prefix Sum HashMap en Árbol | LC 572 (Easy), LC 437 (Med) |
| 28 | Algoritmo de Dijkstra con Min-Heap | 📊 Ver Diagrama | Grokking (Cap. 7) | Relajación Greedy voraz de aristas, Pesos no negativos | LC 743 (Med), LC 1631 (Med) |
Semana 5: Refuerzo, Evaluación y Consolidación Global (Días 29 al 35)#
| Día | Sesión Interactiva | Diagrama de Memoria | Módulo / Enfoque | Patrón Algorítmico Central | Puente LeetCode |
|---|---|---|---|---|---|
| 29 | Evaluación: Arrays, Strings y Two Pointers | 📊 Ver Diagrama | Evaluación Compuesta | Sliding Window HashMap + Punteros voraces O(1) | LC 3 (Med), LC 11 (Med) |
| 30 | Evaluación: Linked Lists In-Place y Heaps | 📊 Ver Diagrama | Evaluación Compuesta | Reconexión topológica in-place + Merge K Sorted Lists | LC 92 (Med), LC 23 (Hard) |
| 31 | Evaluación: Stacks, Queues y Monotonic Stack | 📊 Ver Diagrama | Evaluación Compuesta | Largest Rectangle in Histogram + Decode String | LC 84 (Hard), LC 394 (Med) |
| 32 | Evaluación: Árboles Binarios y BST | 📊 Ver Diagrama | Evaluación Compuesta | Reconstrucción Pre/Inorder + Max Path Sum Bottom-Up | LC 105 (Med), LC 124 (Hard) |
| 33 | Evaluación: Grafos, BFS y Dijkstra | 📊 Ver Diagrama | Evaluación Compuesta | BFS Bidireccional (Word Ladder) + Cheapest Flights | LC 127 (Hard), LC 787 (Med) |
| 34 | Simulacro de Entrevista FAANG Onsite Completo | 📊 Ver Diagrama | Simulacro FAANG | LRU Cache en O(1) + Course Schedule II con Rúbrica | LC 146 (Med), LC 210 (Med) |
| 35 | Examen Global de Consolidación Semanas 1 a 4 | 📊 Ver Diagrama | Consolidación | 25 Preguntas de Active Recall + Matriz de Seniority | Diagnóstico Global L3-L6 |
Semana 6: Algoritmos Voraces (Greedy), Backtracking y Programación Dinámica (Días 36 al 42)#
| Día | Sesión Interactiva | Diagrama de Memoria | Libro / Módulo | Patrón Algorítmico Central | Puente LeetCode |
|---|---|---|---|---|---|
| 36 | Greedy, Set Cover e Interval Scheduling | 📊 Ver Diagrama | Grokking (Cap. 8) | Earliest Finish Time (EFT), Jump Game Voraz | LC 435 (Med), LC 55, LC 45 |
| 37 | Backtracking: Subconjuntos y Paréntesis | 📊 Ver Diagrama | CTCI (Cap. 8, P1) | Invariante Push/Pop, Cascada, Números de Catalan | LC 78 (Med), LC 90, LC 22 |
| 38 | Backtracking: Permutaciones y N-Reinas | 📊 Ver Diagrama | CTCI (Cap. 8, P2) | Poda canónica de ramas hermanas, Diagonales O(1) | LC 46 (Med), LC 47, LC 51 |
| 39 | Programación Dinámica: Triple Step y Robot en Grilla | 📊 Ver Diagrama | CTCI (Cap. 8, P3) | DP 1D optimización O(1) espacio + Matriz 2D con poda | LC 70 (Easy), LC 62, LC 63 |
| 40 | El Problema de la Mochila 0/1 y Partición de Sumas | 📊 Ver Diagrama | Grokking (Cap. 9, P1) | Matriz DP 2D, Optimización 1D con recorrido en reversa | LC 416 (Med), LC 494 (Med) |
| 41 | Cambio de Monedas (Coin Change) y Bucles Duales | 📊 Ver Diagrama | CTCI 8.11 + Grokking | Mochila Ilimitada, Combinaciones vs Permutaciones | LC 322 (Med), LC 518, LC 377 |
| 42 | LCS, Substring Común y Stack of Boxes (LIS 3D) | 📊 Ver Diagrama | Grokking (Cap. 9, P3) | Alineación de secuencias, Patience Sorting O(N log N) | LC 1143 (Med), LC 300, LC 354 |
Semana 7: Manipulación de Bits, Búsqueda Avanzada, Tries y DSU (Días 43 al 49)#
| Día | Sesión Interactiva | Diagrama de Memoria | Libro / Módulo | Patrón Algorítmico Central | Puente LeetCode |
|---|---|---|---|---|---|
| 43 | Fundamentos de Bits: Kernighan, Popcount y XOR | 📊 Ver Diagrama | CTCI (Cap. 5, P1) | Máscaras de Bits, Brian Kernighan n & (n-1), XOR | LC 191 (Easy), LC 338, LC 136 |
| 44 | Manipulación de Bits Avanzada y Vector de Bits | 📊 Ver Diagrama | CTCI (Cap. 5, P2) | Ventana Bitwise, Máscaras Hexadecimales 0xAAAA | LC 461 (Easy), LC 477 (Med) |
| 45 | Búsqueda y Ordenamiento en Arreglos Rotados | 📊 Ver Diagrama | CTCI (Cap. 10, P1) | Teorema de la Mitad Ordenada O(log N), Sparse Search | LC 88 (Easy), LC 33, LC 153 |
| 46 | Búsqueda en Matriz 2D y BST Aumentado | 📊 Ver Diagrama | CTCI (Cap. 10, P2) | Punto de Silla 2D O(M+N), Rank from Stream O(H) | LC 74 (Med), LC 240, LC 280 |
| 47 | Árbol de Prefijos (Trie) y Búsqueda con Comodín | 📊 Ver Diagrama | Grokking (Cap. 11) | Árbol k-ario, Búsqueda O(L), Backtracking con comodín | LC 208 (Med), LC 211 (Med) |
| 48 | Disjoint Set Union (DSU / Union-Find) | 📊 Ver Diagrama | Grokking (Cap. 10/11) | Path Compression + Union by Rank O(lpha(N)) | LC 547 (Med), LC 684, LC 261 |
| 49 | Bitwise Trie Voraz y Cierre Semana 7 | 📊 Ver Diagrama | Consolidación | Max XOR of Two Numbers O(32N) + Kruskal MST | LC 421 (Med), LC 1584 (Med) |
Semana 8: FAANG Hard, Estructuras de Rango y Sistemas de Alto Rendimiento (Días 50 al 56)#
| Día | Sesión Interactiva | Diagrama de Memoria | Libro / Módulo | Patrón Algorítmico Central | Puente LeetCode |
|---|---|---|---|---|---|
| 50 | Trapping Rain Water con 3 Enfoques | 📊 Ver Diagrama | CTCI 17.21 | Arreglos auxiliares, Pila Monótona y Dos Punteros O(1) | LC 42 (Hard), LC 11 (Med) |
| 51 | Cola Monótona y Sliding Window Maximum | 📊 Ver Diagrama | LeetCode 239 Hard | Monotonic Deque, Dominancia temporal amortizada O(N) | LC 239 (Hard), LC 1425 (Hard) |
| 52 | Fenwick Tree (Binary Indexed Tree - BIT) | 📊 Ver Diagrama | Consultas de Rango | Aislamiento LSB i & (-i), Construcción lineal O(N) | LC 307 (Med), LC 315 (Hard) |
| 53 | Segment Tree (Árbol de Segmentos) en 4N | 📊 Ver Diagrama | Consultas de Rango | Segment Tree en array plano 4N, RMQ y Sumas O(log N) | LC 307 (Med), LC 218 (Hard) |
| 54 | Algoritmo de Kadane 1D, Circular y Matriz 2D | 📊 Ver Diagrama | CTCI 17.24 | Invariante de reinicio, Reducción 2D $ o$ 1D en O(R² C) | LC 53 (Med), LC 918, CTCI 17.24 |
| 55 | Criba de Eratóstenes, Kth Multiple y Pow(x, n) | 📊 Ver Diagrama | CTCI 17.9 | Criba desde p², 3 punteros anti-duplicados, Pow O(log N) | LC 204 (Med), LC 264, LC 50 |
| 56 | LFU Cache en O(1) Estricto y Certificación Staff | 📊 Ver Diagrama | Graduación Staff | HashMap + Doubly Linked Lists por frecuencia en O(1) | LC 460 (Hard), LC 146 (Med) |
Semana 9: Algoritmos Avanzados, Probabilísticos y Sistemas Distribuidos (Días 57 al 63)#
| Día | Sesión Interactiva | Diagrama de Memoria | Libro / Módulo | Patrón Algorítmico Central | Puente LeetCode |
|---|---|---|---|---|---|
| 57 | KNN, Métricas de Distancia y Selección | 📊 Ver Diagrama | Grokking (Cap. 10) | Distancias Euclidiana/Manhattan/Coseno, Max-Heap | LC 973 (Med), LC 215 (Med) |
| 58 | Filtros de Bloom y HyperLogLog (HLL) | 📊 Ver Diagrama | Grokking (Cap. 11, P1) | Cero falsos negativos, Cardinalidad con ceros líderes 12KB | LC 705 (Easy/Med), Redis HLL |
| 59 | Índice Invertido y Ponderación TF-IDF | 📊 Ver Diagrama | Grokking (Cap. 11, P2) | Posting lists ordenadas, Dos punteros, Relevancia TF-IDF | LC 349/350, LC 588 (Hard) |
| 60 | Simhash y Locality-Sensitive Hashing (LSH) | 📊 Ver Diagrama | Grokking (Cap. 11, P3) | Deduplicación masiva, Distancia Hamming con XOR popcount | LC 187 (Med), LC 461 (Easy) |
| 61 | Aritmética de Knuth: Euclides Extendido y Diffie-Hellman | 📊 Ver Diagrama | Knuth TAOCP (Vol. 1) | Identidad de Bézout ax+by=gcd, Inverso modular | LC 365 (Med), LC 372 (Med) |
| 62 | Sistemas Distribuidos: Consistent Hashing y Token Bucket | 📊 Ver Diagrama | CTCI Cap. 9 + Grokking | Anillo virtual con Vnodes BTreeMap, Rate Limiter Lazy | LC 359 (Easy), LC 362 (Med) |
| 63 | Super Egg Drop (Problema de los Huevos) y Examen | 📊 Ver Diagrama | CTCI Cap. 6 | Ecuación triangular, Moves DP Invertido O(K · M) | LC 1884 (Med), LC 887 (Hard) |
Semana 10: Evaluación Diagnóstica, Tests Compuestos y Simulacros Staff (Días 64 al 70)#
| Día | Sesión Interactiva | Diagrama de Memoria | Libro / Módulo | Patrón Algorítmico Central | Puente LeetCode |
|---|---|---|---|---|---|
| 64 | Test Diagnóstico 1: Regex Matching y Wildcards | 📊 Ver Diagrama | LeetCode Hard | Programación Dinámica 2D con optimización 1D | LC 10 (Hard), LC 44 (Hard) |
| 65 | Test Diagnóstico 2: Accounts Merge y Word Search II | 📊 Ver Diagrama | LeetCode Hard | Componentes Conexas DSU + Poda in-place en Trie | LC 721 (Med), LC 212 (Hard) |
| 66 | Test Diagnóstico 3: Range Queries y Trapping Rain Water 3D | 📊 Ver Diagrama | LeetCode Hard | DP + Monotonic Deque O(N) + Min-Heap de Frontera 3D | LC 1425 (Hard), LC 407 (Hard) |
| 67 | Test Diagnóstico 4: Sistemas Distribuidos y Probabilísticos | 📊 Ver Diagrama | Sistemas Distribuidos | Token Bucket Lazy + Bloom Filter + Simhash LSH | Cloudflare/Datadog Architecture |
| 68 | Gran Simulacro Onsite FAANG Staff (75 min) | 📊 Ver Diagrama | Staff Mock Interview | Alien Dictionary Kahn + Sliding Window Median Dual-Heap | LC 269 (Hard), LC 480 (Hard) |
| 69 | Examen de Maestría de 30 Preguntas de Active Recall | 📊 Ver Diagrama | Examen Semanas 5-9 | Evocación activa profunda de Bits, Tries, DSU, Árboles y Knuth | Evaluación Integral Staff |
| 70 | Matriz de Certificación Final y Blueprint Staff L6+ | 📊 Ver Diagrama | Certificación Oficial | Blueprint de Graduación Staff, Calendario Spaced Repetition | Graduación Oficial del Curso |
💡 Conexión de Bajo Nivel para Desarrolladores JavaScript / TypeScript#
Como desarrollador con experiencia en JS/TS, tu intuición sobre arrays dinámicos y objetos es valiosa, pero en Rust, Python y en entrevistas de algoritmos aplican reglas de bajo nivel indispensables:
- Arrays en el motor V8 vs Python Lists vs Rust Vectors: En JS, los arreglos inicializan como bloques contiguos en C++ (Fast Packed Elements), pero mutaciones arbitrarias los degradan a tablas hash lentas (Dictionary Mode). En Python,
listes un arreglo dinámico de punteros de 64 bits. En Rust,Vec<T>es un búfer de memoria contigua pura sin intermediarios, optimizado para instrucciones vectoriales SIMD de CPU. - Punteros y Referencias en el Heap: En JS todos los objetos se asignan por referencia en el Heap. Al pasar un nodo:
-
node = node.nextsolo reasigna la variable local en el stack frame (sin mutar la estructura). -node.next = node.next.nextonode.val = ...muta la memoria física en el Heap para todos los que observen la lista. - Identidad de Referencia vs Comparación de Valor: En JS
nodeA === nodeBcompara direcciones de memoria física en el Heap de V8, exactamente igual quenodeA is nodeBen Python o la comparación de punteros crudos en Rust. CompararnodeA.val === nodeB.valsolo verifica igualdad numérica. - El Call Stack y Stack Overflow: En Node.js o el navegador, la recursión profunda satura la pila asignada con
RangeError: Maximum call stack size exceeded(~10,000 marcos). En Python el límite es 1,000. En Rust, un desbordamiento del hilo (2 MB - 8 MB) provoca una terminación abrupta protegida por páginas de guarda. - Estructuras Circulares y Serialización: Si una lista tiene ciclo, intentar imprimirla con
JSON.stringify(head)en JS lanzaráTypeError: Converting circular structure to JSON. En V8, los ciclos huérfanos se recolectan por Mark-and-Sweep. En Rust seguro, el sistema de Ownership prohíbe ciclos directos sin Arena Indexing. - Números Gigantes: En JS los números mayores que
Number.MAX_SAFE_INTEGER(2⁵³ - 1) pierden precisión por el estándar IEEE 754. Operar dígito por dígito con linked lists (CTCI 2.5) es el modelo fundacional deBigInt. - LIFO y FIFO en el Event Loop: El Call Stack síncrono opera como una pila LIFO, mientras que el Microtask Queue (
Promise.then) y el Macrotask Queue (setTimeout) operan como colas FIFO. El uso deshift()para desencolar es O(N) en V8; en Rust se usaVecDequeen O(1) estricto amortizado. - El DOM como Árbol N-ario y Reconciliación en React: El DOM es un árbol jerárquico. Los motores como React utilizan recorridos DFS sobre el árbol de componentes (Fiber Tree) para reconciliar cambios de forma óptima.
- El Garbage Collector como Grafo de Conectividad: Node.js rastrea objetos mediante Mark-and-Sweep desde las GC Roots (variables globales y Call Stack). Todo nodo o ciclo no alcanzable es recolectado. En Rust, el compilador inserta
dropen tiempo de compilación con costo cero en ejecución. - Event Bubbling y Lowest Common Ancestor (LCA): Al despachar un evento en el DOM, este asciende (bubbles up) por los ancestros hasta la raíz. El ancestro común más cercano a dos elementos hermanos (LCA) es el contenedor exacto para ubicar un event listener centralizado (Event Delegation).
- Ausencia de Priority Queue en ECMAScript: JavaScript carece de un Min-Heap nativo en su librería estándar. Ordenar arreglos con
arr.sort()en cada paso de Dijkstra dispara la complejidad a O(V² log V). Un Senior Developer implementa un Min-Heap binario sobre un array plano usando aritmética de índices (2*i + 1,2*i + 2). - La Trampa de los
Mapcon Claves Compuestas en JS: En Python, una tupla de coordenadas(r, c)es inmutable y hashable. En JS,Mapcompara objetos por referencia física ([0, 1] !== [0, 1]), obligando a serializar claves o aplanar índices (r * cols + c). - Ordenamiento Lexicográfico en
Array.prototype.sort(): En JS,[10, 2].sort()produce[10, 2]por conversión a strings. En problemas voraces (Greedy Interval Scheduling), olvidar(a, b) => a[1] - b[1]destruye la garantía de optimalidad asintótica. - Aritmética en Punto Flotante vs Monedas Enteras: En algoritmos de Coin Change o pasarelas de pago (Stripe API), operar con decimales flotantes produce errores de redondeo IEEE 754 (
0.1 + 0.2 !== 0.3). Siempre se opera en enteros base (centavos). - Diffing de Git y Virtual DOM como Longest Common Subsequence (LCS): La alineación óptima de secuencias mediante DP es el fundamento matemático que utilizan
git diffy el reconciliador de React (Fiber) para calcular el número mínimo de mutaciones en el DOM. - Operadores Bitwise y Coerción
ToInt32en V8: En JS los números comunes sonNumber(flotante de 64 bits IEEE 754). Al aplicar operadores bitwise (|,&,^,~,<<,>>), V8 trunca el operando a un entero de 32 bits con signo (ToInt32) antes de ejecutar la instrucción de CPU. TypedArrayyArrayBuffercomo Vectores de Bits Compactos: Crear arreglos normales[]de booleanos consume hasta 8 bytes por elemento en Heap. Un Senior Developer utilizanew Uint32Array(1000)para empaquetar 32,000 banderas binarias en exactamente 4 KB de memoria contigua en C++.- Radix Trees en Enrutadores Web vs Tries: Motores web de altísimo rendimiento como Fastify, Hono y el enrutador de Next.js (
/api/users/:id) no usan expresiones regulares para hacer match de URLs: implementan Radix Trees (Tries comprimidos) que resuelven rutas dinámicas en sub-microsegundos. - Conectividad Dinámica en Aplicaciones Colaborativas: En herramientas como Figma, Miro o Google Docs, la agrupación de elementos en el canvas y la resolución de componentes conexas en tiempo real se modela mediante estructuras de conjuntos disjuntos (DSU / Union-Find) para sincronización con latencia cero.
- Evicción de Caché en V8 y Service Workers (LFU vs LRU): En el Cache Storage API de los navegadores y capas de edge computing (Cloudflare Workers, Fastly VCL), los proxies inversos no usan heurísticas ingenuas: combinan contadores de frecuencia y listas temporales para mitigar escaneos masivos que desalojarían assets calientes.
- TypedArrays Contiguos para Segment Trees y Fenwick Trees: En JS/TS, crear árboles basados en objetos
{ left, right, value }causa fragmentación severa del Heap. Un Senior Staff Engineer asigna un únicoInt32Array(4 * n)para Segment Trees oInt32Array(n + 1)para Fenwick Trees. - BigInt y Aritmética Modular en Criptografía: En JavaScript, cualquier número mayor a
Number.MAX_SAFE_INTEGER(2⁵³ - 1) pierde precisión. Algoritmos de exponenciación modular y primalidad en Node.js exigenBigIntpara evitar corrupciones en firmas criptográficas. - Monotonic Deques sobre Buffers Circulares: En V8,
Array.prototype.shift()es O(N) porque reorganiza la memoria interna. Para mantener ventanas deslizantes de telemetría a 60 FPS sin GC pauses, se implementa un buffer circular con máscara de potencia de 2 (index & (capacity - 1)) sobreInt32Array. - Búsqueda Vectorial y Embeddings en TypeScript: Cosine Similarity y distancia euclidiana implementadas sobre
Float64Arraypara vector stores (pgvector, ChromaDB, Pinecone) en Node.js sin sobrecargar el recolector de basura de V8. - Filtros Probabilísticos en Redis: HyperLogLog (
PFADD/PFCOUNTcon 12 KB fijos) para conteo de DAUs masivos y Bloom Filters (BF.ADD/BF.EXISTScon RedisBloom) para evitar lecturas innecesarias en bases de datos relacionales. - Compresión Delta y Posting Lists en Motores Full-Text: Índices invertidos con dos punteros convergentes y compresión gap (deltas) en librerías de búsqueda como FlexSearch o MiniSearch en Node.js.
- Consistent Hashing y Token Bucket en Microservicios: Consistent Hash Ring con réplicas virtuales para balanceo sin fallas en cascada y control de ráfagas con Token Bucket de evaluación perezosa en middlewares de Express/NestJS.
📝 El Protocolo de 5 Pasos para Resolver en Papel#
Frente a cualquier problema de LeetCode o entrevista, sigue esta disciplina estricta:
[1. Entender] --> [2. Casos Borde] --> [3. Traza en Papel] --> [4. Pseudocódigo] --> [5. Código Rust/Python]
- Entender el problema: Reescribe el enunciado en 1 oración con tus propias palabras. Define entradas y salidas.
- Definir Casos Borde en Papel:
- ¿Qué pasa si la lista o estructura está vacía
Noneo[]? - ¿Qué pasa si tiene un solo elemento[x]? - ¿Qué pasa si hay elementos duplicados o negativos? - ¿Qué pasa si hay ciclos o no existe intersección? - Traza Manual (Dry Run): - Dibuja un ejemplo concreto pequeño (4 a 6 nodos). - Escribe una tabla de variables: columnas para cada puntero y variable de control. - Simula paso a paso qué cambia en cada iteración.
- Pseudocódigo: - Escribe en español o pseudocódigo la lógica antes de preocuparte por la sintaxis.
- Código Limpio y Verificación: - Implementa la solución con tipos estrictos. - Ejecuta las pruebas automatizadas.
🧪 Ejecución de Pruebas Automatizadas#
El proyecto incluye implementaciones verificadas y una suite de pruebas con 141 pruebas unitarias exhaustivas para validar tu comprensión en todos los 70 días del plan:
# Ejecutar todas las pruebas unitarias de Python desde la raíz del proyecto:
py -m unittest practica.test_soluciones -v
# Ejecutar las pruebas unitarias de Rust de las 5 Reglas de Oro:
rustc --test starter_algorithms.rs -o starter_test.exe
.\starter_test.exe
📁 Estructura del Repositorio#
GLOSARIO.md: Glosario Maestro de 106 conceptos en 4 capas cognitivas y modelos de hardware en Rust y Python.glossary/README.md: Réplica sincronizada del glosario maestro con rutas relativas a la suite de diagramas.diagrams/: Suite visual con 80 diagramas SVG panorámicos y de sesión diaria.diagrams/README.md: Documentación completa de la arquitectura visual de memoria y diccionario de notación física.sesiones/: Contiene las 70 lecciones interactivas en Markdown con teoría profunda, diagramas de hardware, trazas en papel, preguntas de active recall y código fuente.practica/: Código Python limpio, modular y tipado con las soluciones de referencia de los 70 días.practica/test_soluciones.py: Pruebas unitarias de cobertura exhaustiva (141 pruebas pasando al 100%).