NOTAS DEL TALLERISTA
Clase 18 · Ciclo ago – dic 2026

Two pointers& sliding window

Dos formas de no recalcular lo que ya sabes.

Club de Programación Competitiva
Jueves 15 de octubre · 14:00 – 16:00
Inventario de entrada

Esto ya lo conocen.
No lo expliques de nuevo.

arreglos
índices
for
while
funciones
vectores
long long
sort clase 14
prefix sum clase 17
Objetivo

Salir con dos formas de no recalcular lo que ya sabes…

…y con el hábito de preguntarse qué cambia entre un paso y el siguiente.

Apertura

¿Cuántas sumas tienes que hacer para encontrar el mejor bloque de 3 números consecutivos…

…en 100,000 elementos?

I
Primera cadena · ventana fija

¿Qué cambia de un bloque al siguiente?

El problema

¿Cuál es la suma máxima de un bloque de tamaño k?

La forma directa: sumar cada bloque desde cero.

int mejor = -1000000000;
for (int i = 0; i + k <= n; i++) {
    int suma = 0;
    for (int j = i; j < i + k; j++)
        suma += a[j];
    if (suma > mejor)
        mejor = suma;
}
cout << mejor << "\n";
Contar primero

¿Cuántas operaciones hace esto, aproximadamente?

ciclo de afuera
n
×
ciclo de adentro
k
→
recién ahí aparece
O(n·k)
¿Qué palabra hay que precisar?
desde cero

Cada bloque se suma completo otra vez, aunque casi todo se repite.

Restar lo que sale, sumar lo que entra

Una suma y una resta por paso, sin importar cuánto mida el bloque.

→ PARA DESLIZAR LA VENTANA
int suma = 0;
for (int j = 0; j < k; j++)
    suma += a[j];

int mejor = suma;
for (int i = k; i < n; i++) {
    suma += a[i];       // entra a[i]
    suma -= a[i - k];   // sale a[i - k]
    if (suma > mejor)
        mejor = suma;
}
cout << mejor << "\n";
¿Y ahora cuántas operaciones?

Primero el bloque inicial: k.

Después un solo ciclo de n, con dos operaciones por paso.

O(n)
Idea clave

Ventana fija: el tamaño no cambia, la ventana solo se desliza.

¿Cuál es el error más común aquí?

Restar el elemento equivocado.

Pregunta de control: si k = 3 y estás en i = 5, ¿qué elemento sale?

Sale a[2], no a[3].

II
Segunda cadena · ventana variable

¿Y si el tamaño de la ventana no es fijo?

El problema

¿Cuál es el subarreglo más largo cuya suma no pasa de S?

Tamaño variable: no puedes saber de antemano cuánto mide la respuesta.

más largo

Para probar cada longitud habría que revisar todos los subarreglos:

O(n²)
¿Podemos avanzar sin volver a mirar lo que ya revisamos?

Agrandas por la derecha mientras cabe; cuando no cabe, achicas por la izquierda.

S = 6 · → PARA AVANZAR
int izq = 0;
long long suma = 0;
int mejor = 0;
for (int der = 0; der < n; der++) {
    suma += a[der];
    while (suma > S) {
        suma -= a[izq];
        izq++;
    }
    if (der - izq + 1 > mejor)
        mejor = der - izq + 1;
}
cout << mejor << "\n";
Pregunta para el grupo

¿Qué pasa si cambias while por if?

Sin responder todavía. Lo retomamos más adelante.

Corrección preventiva

¿Siempre funciona la ventana variable?

No.

Con números negativos, sacar un elemento puede aumentar la suma, y el criterio de encoger deja de servir.

[ −4, 3, 2 ] → suma 1 sacas −4 → [ 3, 2 ] → suma 5

El criterio de esta clase asume elementos positivos.

Complejidad

¿Cuántas veces se mueve cada puntero en total?

Cada extremo solo avanza hacia la derecha, nunca retrocede. Cada uno se mueve a lo más n veces.

O(n)

Dos punteros que avanzan en la misma dirección y nunca retroceden.

III
Tercera cadena · two pointers

Un par que suma X

Dos extremos que caminan el uno hacia el otro.

El problema

En un arreglo ordenado, ¿hay dos números que sumen X?

Lo directo son todos los pares:

O(n²)
todos

Si el arreglo está ordenado, puedes descartar pares completos.

Si la suma actual es mayor que X, ¿qué conviene mover?

Mayor que X → mueve j · menor que X → mueve i

El extremo derecho es el más grande; el izquierdo, el más chico.

X = 11 · → PARA AVANZAR
int i = 0, j = n - 1;
while (i < j) {
    long long s = a[i] + a[j];
    if (s == X) {
        cout << a[i] << " " << a[j] << "\n";
        return 0;
    }
    if (s < X)
        i++;
    else
        j--;
}
cout << "No hay\n";
¿Cuántas operaciones hace?

Cada paso mueve un puntero hacia el centro. Como mucho n pasos.

O(n)

+ el costo de sort que ya conocen.

Idea clave

Un arreglo ordenado permite descartar pares, no solo mirarlos.

Par de contraste

Dos parejas que se confunden

ventana fija
→
el tamaño es dado, la ventana se desliza
ventana variable
→
el tamaño depende de una condición
two pointers
→
dos extremos sobre un arreglo ordenado, puede que no sean contiguos
sliding window
→
un bloque contiguo que se mueve
¿Con qué se confunden?

La mayoría piensa que dos punteros siempre significa ventana.

¿El par que suma X es un bloque contiguo?

Error interesante · encoger con if en vez de while

Entrada: a = 1 1 1 4  S = 3

¿Cuántas veces tienes que encoger aquí?

der = 0, 1, 2 → suma 3, ventana válidader = 3 → suma 7, con if sale solo a[0]: suma 6, sigue inválida

La ventana sigue inválida y el programa sigue contando sobre ella. El while existe por esto.

Ejercicios · obligatorios
01

Suma máxima de k consecutivos

ventana fija

Practica el paso de restar y sumar.

02

Par que suma X en arreglo ordenado

two pointers

Practica mover el puntero correcto.

03

Número de bloques con suma exacta S

ventana · positivos

Practica la condición de encoger.

Los nombres son referencias: búscalos en omegaUp.

Recomendados y reto
04 · RECOMENDADO

Subarreglo más largo con suma ≤ S

Ventana variable completa.

05 · RECOMENDADO

Triples con suma cero en arreglo ordenado

Un ciclo fijo y two pointers adentro. ¿Complejidad? O(n²), no O(n³).

06 · RETO

Bloque más corto con suma ≥ S

Ventana variable en sentido contrario: encoger cuando ya se cumple.

07 · RETO

El 4, con restricción

Solo for, while y una función cabe(). Sin sort, sin vectores auxiliares.

Cierre · pregunta de complejidad

¿Por qué la ventana variable es O(n) aunque tenga un while adentro del for?

Cada puntero se mueve a lo más n veces en total, no por iteración del for.

Inventario de cierre
sliding window fija y variable
two pointers arreglo ordenado
amortizado a lo más n movimientos
Tarea

1 – 3 obligatorios · 4 y 5 recomendados · 6 y 7 reto

Club de Programación Competitiva