study.plynte.com
@franguh
Estado de Lectura Marca tu progreso local en tu navegador (iPad / Móvil / Desktop)

🚀 Plan Maestro de Maestría Algorítmica y Arquitectura de Memoria (70 Días / 10 Semanas: Rust & Python)#

Mapa de 10 Semanas de Algoritmos en Rust y Python
Mapa de 10 Semanas de Algoritmos en Rust y 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)#

⚡ Acceso Directo por Semanas:#


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:

  1. 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) y cap (capacidad total asignada).
  2. 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.
  3. 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!
  4. Diferenciación de Flechas: - Flecha sólida continua: Puntero dueño exclusivo (Ownership, por ejemplo un Box<Node> o Vec<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 - 1 desborda a 18,446,744,073,709,551,615 provocando un pánico en depuración.
  • Si en búsqueda binaria calculas high = mid - 1; cuando mid == 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 hace high = mid; (¡cero restas a cero!). O bien utilizar el método seguro mid.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, -1 no existe conceptualmente. Si intentas retornar -1i32 y convertirlo a usize, 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, None si no existe). El compilador te obliga a desarmar el Option con match o if 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)). Usa VecDeque::new() con push_back y pop_front en O(1) estricto amortizado.
  • Min-Heap vs Max-Heap: En Python, heapq es un Min-Heap por defecto. En Rust, BinaryHeap es un Max-Heap por defecto. Para obtener un Min-Heap en Rust, envuelve los valores en std::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 un Vec<Node> contiguo y usar enteros usize como 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:

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);
    }
}
POWERSHELL
# 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].

  1. ¿Qué ocurre exactamente en la memoria física RAM (Stack y Heap) en Python?
  2. ¿Qué ocurre en Rust si utilizas un slice prestado let left_half = &arr[0..mid];?
  3. ¿Cómo impacta esto en la complejidad espacial auxiliar global si la recursión tiene una profundidad de log₂ N?

Respuesta Paso a Paso:

  1. 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.
  2. 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 i32 y 8 bytes con la longitud len).
  3. 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:

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:

  1. Fallo en Línea A: Si arr es un slice vacío (len == 0), 0usize - 1 produce un *subdesbordamiento (underflow)*. En modo depuración el programa se detiene con panic! '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.
  2. Fallo en Línea C: Si low + high excede 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;.
  3. Fallo en Línea D: Si target es menor que el elemento en el índice 0, mid valdrá 0. Ejecutar high = 0usize - 1 detona un pánico inmediato de underflow en la CPU.
  4. 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:

  1. ¿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;?
  2. ¿Por qué Rust utiliza el algoritmo criptográficamente resistente SipHash 1-3 por defecto en su HashMap en lugar de un algoritmo más rápido como FNV o MurmurHash?

Respuesta Paso a Paso:

  1. Doble Consulta vs Entrada Única: - El código ingenuo con contains_key ejecuta 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 V a los bytes de esa celda en el Heap, actualizando el contador in-place en un tercio de las instrucciones de CPU.
  2. 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)).

  1. ¿Qué camino matemático encontrará el algoritmo de Rust y por qué?
  2. ¿Cómo se corrige utilizando la librería estándar de Rust sin multiplicar distancias por -1?
  3. ¿Por qué es obligatoria la verificación if d > dist[u] { continue; } al extraer del heap?

Respuesta Paso a Paso:

  1. Max-Heap vs Min-Heap: Por diseño estándar, BinaryHeap en 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.
  2. Corrección con Reverse: Se envuelve la distancia o la tupla completa con el adaptador std::cmp::Reverse: ``rust pq.push((Reverse(dist), node)); // Al extraer: let (Reverse(d), u) = pq.pop().unwrap(); ` Reverse invierte las comparaciones del trait Ord` en compilación con cero costo de CPU.
  3. *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.

  1. Explica este fenómeno desde primeros principios de hardware: líneas de caché L1/L2/L3, localidad espacial y cache misses.
  2. ¿Por qué la técnica de Arena Indexing (Vec<Node>) es el estándar de oro para grafos y árboles en Rust frente a punteros Rc<RefCell<Node>>?

Respuesta Paso a Paso:

  1. 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 puntero next requiere 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.
  2. 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 enteros usize o u32, 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:

  1. 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.
  1. 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).
  1. 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.
  1. 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)#

Arreglos, Búsqueda Binaria y Dos Punteros
Arreglos, Búsqueda Binaria y Dos Punteros

DíaSesión InteractivaDiagrama de MemoriaLibro / MóduloPatrón Algorítmico CentralPuente LeetCode
01Búsqueda Binaria, Invariantes y Logaritmos📊 Ver DiagramaGrokking (Cap. 1, P1)Divide & Conquer / Reducción a la mitadLC 704 (Easy), LC 35 (Easy)
02Big O: Complejidad Asintótica y Espacio📊 Ver DiagramaGrokking (Cap. 1, P2)Análisis asintótico y Marcos del Call StackEjercicios analíticos en papel
03Memoria RAM, Arreglos y Strings In-Place📊 Ver DiagramaCTCI (Cap. 1, P1)Is Unique: Bit Vector & URLify back-to-frontLC 344 (Easy), LC 217 (Easy)
04Hash Maps y Conteo de Frecuencia📊 Ver DiagramaCTCI (Cap. 1, P2)Check Permutation & Palindrome Bit ToggleLC 242 (Easy), LC 1 (Easy), LC 49 (Med)
05Técnica de Dos Punteros Convergentes vs Lector/Escritor📊 Ver DiagramaCTCI (Cap. 1, P3)In-Place Array Mutation y MonotonicidadLC 125 (Easy), LC 26 (Easy), LC 167 (Med)
06Strings Avanzados, RLE y Rotaciones📊 Ver DiagramaCTCI (Cap. 1, P4)Invariantes de estado, RLE y Concatenación s₁+s₁LC 161 (Med), LC 443 (Med)
07Matrices 2D y Consolidación Semana 1📊 Ver DiagramaCTCI (Cap. 1, P5)Rotate Matrix 90° & Zero Matrix O(1) spaceLC 48 (Med), LC 73 (Med)

Semana 2: Memoria Dinámica, Recursión y Listas Enlazadas (Días 08 al 14)#

Recursión, Call Stack y Listas vs Arena
Recursión, Call Stack y Listas vs Arena

DíaSesión InteractivaDiagrama de MemoriaLibro / MóduloPatrón Algorítmico CentralPuente LeetCode
08Memoria RAM: Arreglos vs Listas Enlazadas📊 Ver DiagramaGrokking (Cap. 2)Acceso O(1) vs O(N), Nodos Heap, Selection SortLC 206 (Easy), LC 912 (Med)
09Recursión y Anatomía del Call Stack📊 Ver DiagramaGrokking (Cap. 3)Caso Base, Stack Frames, LIFO, Inversión RecursivaLC 509 (Easy), LC 206 (Easy)
10Técnica Runner y Detección de Duplicados📊 Ver DiagramaCTCI (Cap. 2, P1)Remove Dups con Buffer y Ventana de K pasosLC 83 (Easy), LC 19 (Med)
11Borrado Intermedio y Partición con Centinelas📊 Ver DiagramaCTCI (Cap. 2, P2)Mutación de Contenido in-place vs Dummy NodesLC 237 (Med), LC 86 (Med)
12Suma de Listas Big/Little Endian y Palíndromos📊 Ver DiagramaCTCI (Cap. 2, P3)Aritmética arbitraria, Inversión de mitad O(1)LC 2 (Med), LC 234 (Easy)
13Intersección de Listas y Detección de Ciclos de Floyd📊 Ver DiagramaCTCI (Cap. 2, P4)Topología en "Y", Ecuación k=nC-m, Liebre y TortugaLC 160 (Easy), LC 141, LC 142
14Consolidación Global Semana 2 y Simulacro📊 Ver DiagramaConsolidaciónLos 5 Patrones de Oro de Listas EnlazadasLC 21 (Easy), LC 143 (Med)

Semana 3: Divide & Conquer, Hash Tables Avanzadas, Stacks & Queues y Monotonic Stack (Días 15 al 21)#

Tablas Hash, Pilas, Colas y Pila Monótona
Tablas Hash, Pilas, Colas y Pila Monótona

DíaSesión InteractivaDiagrama de MemoriaLibro / MóduloPatrón Algorítmico CentralPuente LeetCode
15Divide y Vencerás, Quicksort y Quickselect📊 Ver DiagramaGrokking (Cap. 4)Invariante Lomuto, Caso promedio O(N log N), QuickselectLC 912 (Med), LC 215 (Med)
16Hash Tables Avanzadas: Linear Probing y Rehashing📊 Ver DiagramaGrokking (Cap. 5)Factor de carga lpha, Lápidas, SwissTableLC 706 (Easy), LC 380 (Med)
17Fundamentos de Stacks & Queues y Three in One📊 Ver DiagramaCTCI (Cap. 3, P1)LIFO vs FIFO en RAM, Particiones Fijas en 1 ArrayLC 20 (Easy), LC 225 (Easy)
18Stack Min O(1) y Pila de Platos (SetOfStacks)📊 Ver DiagramaCTCI (Cap. 3, P2)Pila Auxiliar de Mínimos con Conteo, Arrays de PilasLC 155 (Med), LC 1172 (Hard)
19Cola mediante Pilas (Queue via Stacks) y Sort Stack📊 Ver DiagramaCTCI (Cap. 3, P3)Doble Inversión LIFO $ o$ FIFO, Transferencia LazyLC 232 (Easy), LC 225 (Easy)
20Refugio de Animales (Animal Shelter) y FIFO Selectivo📊 Ver DiagramaCTCI (Cap. 3, P4)FIFO con Timestamps Duales, Sincronización O(1)LC 981 (Med), Diseño OOP
21Patrón Pila Monótona y Consolidación Semana 3📊 Ver DiagramaConsolidaciónNext Greater Element O(N) amortizado, Línea de VisiónLC 739 (Med), LC 496, LC 503

Semana 4: Grafos, Árboles Binarios, BST, Orden Topológico y Dijkstra (Días 22 al 28)#

Jerarquía de Árboles, Heaps, Grafos y Dijkstra
Jerarquía de Árboles, Heaps, Grafos y Dijkstra

DíaSesión InteractivaDiagrama de MemoriaLibro / MóduloPatrón Algorítmico CentralPuente LeetCode
22Grafos, Listas de Adyacencia y BFS📊 Ver DiagramaGrokking (Cap. 6)Cola FIFO, Set visited, Caminos mínimos en no ponderadosLC 1971 (Easy), LC 102 (Med)
23Árboles Binarios, Recorridos y Minimal Tree📊 Ver DiagramaCTCI (Cap. 4, P1)Recorridos In/Pre/Post/Level, Bisección Divide & ConquerLC 108 (Easy), LC 102 (Med)
24Validación de BST y Comprobación de Balanceo📊 Ver DiagramaCTCI (Cap. 4, P2)Propagación de cotas (low, high), Post-order O(N)LC 98 (Med), LC 110 (Easy)
25Sucesor en BST y Ancestro Común Más Bajo (LCA)📊 Ver DiagramaCTCI (Cap. 4, P3)Topología de ancestros, Post-order divergente en árbolLC 285 (Med), LC 236 (Med)
26Orden Topológico y Algoritmo de Kahn📊 Ver DiagramaCTCI (Cap. 4, P4)In-degrees, DAG acíclico, Detección de ciclos dirigidaLC 207 (Med), LC 210 (Med)
27Verificación de Subárboles y Paths with Sum📊 Ver DiagramaCTCI (Cap. 4, P5)Pre-order serialization, Prefix Sum HashMap en ÁrbolLC 572 (Easy), LC 437 (Med)
28Algoritmo de Dijkstra con Min-Heap📊 Ver DiagramaGrokking (Cap. 7)Relajación Greedy voraz de aristas, Pesos no negativosLC 743 (Med), LC 1631 (Med)

Semana 5: Refuerzo, Evaluación y Consolidación Global (Días 29 al 35)#

Jerarquía de Árboles, Heaps, Grafos y Dijkstra
Jerarquía de Árboles, Heaps, Grafos y Dijkstra

DíaSesión InteractivaDiagrama de MemoriaMódulo / EnfoquePatrón Algorítmico CentralPuente LeetCode
29Evaluación: Arrays, Strings y Two Pointers📊 Ver DiagramaEvaluación CompuestaSliding Window HashMap + Punteros voraces O(1)LC 3 (Med), LC 11 (Med)
30Evaluación: Linked Lists In-Place y Heaps📊 Ver DiagramaEvaluación CompuestaReconexión topológica in-place + Merge K Sorted ListsLC 92 (Med), LC 23 (Hard)
31Evaluación: Stacks, Queues y Monotonic Stack📊 Ver DiagramaEvaluación CompuestaLargest Rectangle in Histogram + Decode StringLC 84 (Hard), LC 394 (Med)
32Evaluación: Árboles Binarios y BST📊 Ver DiagramaEvaluación CompuestaReconstrucción Pre/Inorder + Max Path Sum Bottom-UpLC 105 (Med), LC 124 (Hard)
33Evaluación: Grafos, BFS y Dijkstra📊 Ver DiagramaEvaluación CompuestaBFS Bidireccional (Word Ladder) + Cheapest FlightsLC 127 (Hard), LC 787 (Med)
34Simulacro de Entrevista FAANG Onsite Completo📊 Ver DiagramaSimulacro FAANGLRU Cache en O(1) + Course Schedule II con RúbricaLC 146 (Med), LC 210 (Med)
35Examen Global de Consolidación Semanas 1 a 4📊 Ver DiagramaConsolidación25 Preguntas de Active Recall + Matriz de SeniorityDiagnóstico Global L3-L6

Semana 6: Algoritmos Voraces (Greedy), Backtracking y Programación Dinámica (Días 36 al 42)#

Paradigmas de Decisión: Greedy, Backtracking y DP
Paradigmas de Decisión: Greedy, Backtracking y DP

DíaSesión InteractivaDiagrama de MemoriaLibro / MóduloPatrón Algorítmico CentralPuente LeetCode
36Greedy, Set Cover e Interval Scheduling📊 Ver DiagramaGrokking (Cap. 8)Earliest Finish Time (EFT), Jump Game VorazLC 435 (Med), LC 55, LC 45
37Backtracking: Subconjuntos y Paréntesis📊 Ver DiagramaCTCI (Cap. 8, P1)Invariante Push/Pop, Cascada, Números de CatalanLC 78 (Med), LC 90, LC 22
38Backtracking: Permutaciones y N-Reinas📊 Ver DiagramaCTCI (Cap. 8, P2)Poda canónica de ramas hermanas, Diagonales O(1)LC 46 (Med), LC 47, LC 51
39Programación Dinámica: Triple Step y Robot en Grilla📊 Ver DiagramaCTCI (Cap. 8, P3)DP 1D optimización O(1) espacio + Matriz 2D con podaLC 70 (Easy), LC 62, LC 63
40El Problema de la Mochila 0/1 y Partición de Sumas📊 Ver DiagramaGrokking (Cap. 9, P1)Matriz DP 2D, Optimización 1D con recorrido en reversaLC 416 (Med), LC 494 (Med)
41Cambio de Monedas (Coin Change) y Bucles Duales📊 Ver DiagramaCTCI 8.11 + GrokkingMochila Ilimitada, Combinaciones vs PermutacionesLC 322 (Med), LC 518, LC 377
42LCS, Substring Común y Stack of Boxes (LIS 3D)📊 Ver DiagramaGrokking (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)#

Manipulación de Bits, Tries y Disjoint Set Union
Manipulación de Bits, Tries y Disjoint Set Union

DíaSesión InteractivaDiagrama de MemoriaLibro / MóduloPatrón Algorítmico CentralPuente LeetCode
43Fundamentos de Bits: Kernighan, Popcount y XOR📊 Ver DiagramaCTCI (Cap. 5, P1)Máscaras de Bits, Brian Kernighan n & (n-1), XORLC 191 (Easy), LC 338, LC 136
44Manipulación de Bits Avanzada y Vector de Bits📊 Ver DiagramaCTCI (Cap. 5, P2)Ventana Bitwise, Máscaras Hexadecimales 0xAAAALC 461 (Easy), LC 477 (Med)
45Búsqueda y Ordenamiento en Arreglos Rotados📊 Ver DiagramaCTCI (Cap. 10, P1)Teorema de la Mitad Ordenada O(log N), Sparse SearchLC 88 (Easy), LC 33, LC 153
46Búsqueda en Matriz 2D y BST Aumentado📊 Ver DiagramaCTCI (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 DiagramaGrokking (Cap. 11)Árbol k-ario, Búsqueda O(L), Backtracking con comodínLC 208 (Med), LC 211 (Med)
48Disjoint Set Union (DSU / Union-Find)📊 Ver DiagramaGrokking (Cap. 10/11)Path Compression + Union by Rank O(lpha(N))LC 547 (Med), LC 684, LC 261
49Bitwise Trie Voraz y Cierre Semana 7📊 Ver DiagramaConsolidaciónMax XOR of Two Numbers O(32N) + Kruskal MSTLC 421 (Med), LC 1584 (Med)

Semana 8: FAANG Hard, Estructuras de Rango y Sistemas de Alto Rendimiento (Días 50 al 56)#

Consultas de Rango: Fenwick, Segment Trees y LFU Cache
Consultas de Rango: Fenwick, Segment Trees y LFU Cache

DíaSesión InteractivaDiagrama de MemoriaLibro / MóduloPatrón Algorítmico CentralPuente LeetCode
50Trapping Rain Water con 3 Enfoques📊 Ver DiagramaCTCI 17.21Arreglos auxiliares, Pila Monótona y Dos Punteros O(1)LC 42 (Hard), LC 11 (Med)
51Cola Monótona y Sliding Window Maximum📊 Ver DiagramaLeetCode 239 HardMonotonic Deque, Dominancia temporal amortizada O(N)LC 239 (Hard), LC 1425 (Hard)
52Fenwick Tree (Binary Indexed Tree - BIT)📊 Ver DiagramaConsultas de RangoAislamiento LSB i & (-i), Construcción lineal O(N)LC 307 (Med), LC 315 (Hard)
53Segment Tree (Árbol de Segmentos) en 4N📊 Ver DiagramaConsultas de RangoSegment Tree en array plano 4N, RMQ y Sumas O(log N)LC 307 (Med), LC 218 (Hard)
54Algoritmo de Kadane 1D, Circular y Matriz 2D📊 Ver DiagramaCTCI 17.24Invariante de reinicio, Reducción 2D $ o$ 1D en O(R² C)LC 53 (Med), LC 918, CTCI 17.24
55Criba de Eratóstenes, Kth Multiple y Pow(x, n)📊 Ver DiagramaCTCI 17.9Criba desde p², 3 punteros anti-duplicados, Pow O(log N)LC 204 (Med), LC 264, LC 50
56LFU Cache en O(1) Estricto y Certificación Staff📊 Ver DiagramaGraduación StaffHashMap + 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)#

Sistemas Distribuidos y Algoritmos Probabilísticos
Sistemas Distribuidos y Algoritmos Probabilísticos

DíaSesión InteractivaDiagrama de MemoriaLibro / MóduloPatrón Algorítmico CentralPuente LeetCode
57KNN, Métricas de Distancia y Selección📊 Ver DiagramaGrokking (Cap. 10)Distancias Euclidiana/Manhattan/Coseno, Max-HeapLC 973 (Med), LC 215 (Med)
58Filtros de Bloom y HyperLogLog (HLL)📊 Ver DiagramaGrokking (Cap. 11, P1)Cero falsos negativos, Cardinalidad con ceros líderes 12KBLC 705 (Easy/Med), Redis HLL
59Índice Invertido y Ponderación TF-IDF📊 Ver DiagramaGrokking (Cap. 11, P2)Posting lists ordenadas, Dos punteros, Relevancia TF-IDFLC 349/350, LC 588 (Hard)
60Simhash y Locality-Sensitive Hashing (LSH)📊 Ver DiagramaGrokking (Cap. 11, P3)Deduplicación masiva, Distancia Hamming con XOR popcountLC 187 (Med), LC 461 (Easy)
61Aritmética de Knuth: Euclides Extendido y Diffie-Hellman📊 Ver DiagramaKnuth TAOCP (Vol. 1)Identidad de Bézout ax+by=gcd, Inverso modularLC 365 (Med), LC 372 (Med)
62Sistemas Distribuidos: Consistent Hashing y Token Bucket📊 Ver DiagramaCTCI Cap. 9 + GrokkingAnillo virtual con Vnodes BTreeMap, Rate Limiter LazyLC 359 (Easy), LC 362 (Med)
63Super Egg Drop (Problema de los Huevos) y Examen📊 Ver DiagramaCTCI Cap. 6Ecuació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)#

Mapa de 10 Semanas de Algoritmos en Rust y Python
Mapa de 10 Semanas de Algoritmos en Rust y Python

DíaSesión InteractivaDiagrama de MemoriaLibro / MóduloPatrón Algorítmico CentralPuente LeetCode
64Test Diagnóstico 1: Regex Matching y Wildcards📊 Ver DiagramaLeetCode HardProgramación Dinámica 2D con optimización 1DLC 10 (Hard), LC 44 (Hard)
65Test Diagnóstico 2: Accounts Merge y Word Search II📊 Ver DiagramaLeetCode HardComponentes Conexas DSU + Poda in-place en TrieLC 721 (Med), LC 212 (Hard)
66Test Diagnóstico 3: Range Queries y Trapping Rain Water 3D📊 Ver DiagramaLeetCode HardDP + Monotonic Deque O(N) + Min-Heap de Frontera 3DLC 1425 (Hard), LC 407 (Hard)
67Test Diagnóstico 4: Sistemas Distribuidos y Probabilísticos📊 Ver DiagramaSistemas DistribuidosToken Bucket Lazy + Bloom Filter + Simhash LSHCloudflare/Datadog Architecture
68Gran Simulacro Onsite FAANG Staff (75 min)📊 Ver DiagramaStaff Mock InterviewAlien Dictionary Kahn + Sliding Window Median Dual-HeapLC 269 (Hard), LC 480 (Hard)
69Examen de Maestría de 30 Preguntas de Active Recall📊 Ver DiagramaExamen Semanas 5-9Evocación activa profunda de Bits, Tries, DSU, Árboles y KnuthEvaluación Integral Staff
70Matriz de Certificación Final y Blueprint Staff L6+📊 Ver DiagramaCertificación OficialBlueprint de Graduación Staff, Calendario Spaced RepetitionGraduació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:

  1. 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, list es 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.
  2. Punteros y Referencias en el Heap: En JS todos los objetos se asignan por referencia en el Heap. Al pasar un nodo: - node = node.next solo reasigna la variable local en el stack frame (sin mutar la estructura). - node.next = node.next.next o node.val = ... muta la memoria física en el Heap para todos los que observen la lista.
  3. Identidad de Referencia vs Comparación de Valor: En JS nodeA === nodeB compara direcciones de memoria física en el Heap de V8, exactamente igual que nodeA is nodeB en Python o la comparación de punteros crudos en Rust. Comparar nodeA.val === nodeB.val solo verifica igualdad numérica.
  4. 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.
  5. 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.
  6. 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 de BigInt.
  7. 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 de shift() para desencolar es O(N) en V8; en Rust se usa VecDeque en O(1) estricto amortizado.
  8. 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.
  9. 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 drop en tiempo de compilación con costo cero en ejecución.
  10. 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).
  11. 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).
  12. La Trampa de los Map con Claves Compuestas en JS: En Python, una tupla de coordenadas (r, c) es inmutable y hashable. En JS, Map compara objetos por referencia física ([0, 1] !== [0, 1]), obligando a serializar claves o aplanar índices (r * cols + c).
  13. 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.
  14. 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).
  15. 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 diff y el reconciliador de React (Fiber) para calcular el número mínimo de mutaciones en el DOM.
  16. Operadores Bitwise y Coerción ToInt32 en V8: En JS los números comunes son Number (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.
  17. TypedArray y ArrayBuffer como Vectores de Bits Compactos: Crear arreglos normales [] de booleanos consume hasta 8 bytes por elemento en Heap. Un Senior Developer utiliza new Uint32Array(1000) para empaquetar 32,000 banderas binarias en exactamente 4 KB de memoria contigua en C++.
  18. 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.
  19. 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.
  20. 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.
  21. 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 único Int32Array(4 * n) para Segment Trees o Int32Array(n + 1) para Fenwick Trees.
  22. 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 exigen BigInt para evitar corrupciones en firmas criptográficas.
  23. 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)) sobre Int32Array.
  24. Búsqueda Vectorial y Embeddings en TypeScript: Cosine Similarity y distancia euclidiana implementadas sobre Float64Array para vector stores (pgvector, ChromaDB, Pinecone) en Node.js sin sobrecargar el recolector de basura de V8.
  25. Filtros Probabilísticos en Redis: HyperLogLog (PFADD/PFCOUNT con 12 KB fijos) para conteo de DAUs masivos y Bloom Filters (BF.ADD/BF.EXISTS con RedisBloom) para evitar lecturas innecesarias en bases de datos relacionales.
  26. 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.
  27. 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:

TEXT
[1. Entender] --> [2. Casos Borde] --> [3. Traza en Papel] --> [4. Pseudocódigo] --> [5. Código Rust/Python]
  1. Entender el problema: Reescribe el enunciado en 1 oración con tus propias palabras. Define entradas y salidas.
  2. Definir Casos Borde en Papel: - ¿Qué pasa si la lista o estructura está vacía None o []? - ¿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?
  3. 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.
  4. Pseudocódigo: - Escribe en español o pseudocódigo la lógica antes de preocuparte por la sintaxis.
  5. 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:

POWERSHELL
# 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%).
Estado de Lectura Marca tu progreso local en tu navegador (iPad / Móvil / Desktop)