Pular para o conteúdo

Algoritmos e estruturas de dados · Técnicas · 5 min de leitura

Dois ponteiros e janela deslizante

Dois índices que andam pelo array trocam um laço aninhado O(n²) por uma passada O(n): par com soma alvo, remover duplicados, maior soma de k seguidos e a maior substring sem repetir letras.

1 + 15 = 16 → 1 + 11 = 1211 + 11 = 12 → 2 + 11 = 1322 + 11 = 13 → 4 + 11 = 1531 + 15 = 16 — maior → R anda1 + 15 = 16maior → R anda1 + 11 = 12 — menor → L anda1 + 11 = 12menor → L anda2 + 11 = 13 — menor → L anda2 + 11 = 13menor → L anda4 + 11 = 15 — achou4 + 11 = 15achou

Arraste para o lado para ver o diagrama inteiro.

L começa no início e R no fim. Soma grande demais: R volta uma casa; pequena demais: L avança. Como a lista está ordenada, nenhum par possível é pulado.

Dois ponteiros

Com o array ordenado, um ponteiro no início e outro no fim: se a soma passou do alvo, só diminuir ajuda (R anda para trás); se faltou, só aumentar ajuda (L anda para frente). Cada passo descarta uma posição, então são no máximo n passos — O(n) em vez de testar todos os pares, O(n²). A mesma ideia remove duplicados em uma lista ordenada e inverte arrays no lugar.

Janela deslizante

Para perguntas sobre trechos seguidos (subarray, substring), mantenha uma janela [L, R]. Ao avançar R, some o que entrou; ao avançar L, subtraia o que saiu. Janela fixa: maior soma de k dias seguidos. Janela variável: maior substring sem letra repetida, menor trecho que soma pelo menos X. Cada elemento entra e sai uma vez: O(n).

Quando pensar nisso

Sinais: "array ordenado", "par/trio que soma", "subarray contínuo", "substring", "k elementos seguidos". Se a pergunta é sobre qualquer subconjunto (não contínuo), a janela não serve — aí costuma ser hash ou programação dinâmica.

No código: antes e depois

✗ AntesTypeScript
// O(n · k): soma k itens de novo para cada posição
function maiorSoma(v: number[], k: number): number {
  let melhor = -Infinity;
  for (let i = 0; i + k <= v.length; i++) {
    let s = 0;
    for (let j = i; j < i + k; j++) s += v[j];
    melhor = Math.max(melhor, s);
  }
  return melhor;
}
✓ DepoisTypeScript
// O(n): a janela anda uma casa — entra v[r], sai v[r - k]
function maiorSoma(v: number[], k: number): number {
  let s = 0;
  for (let r = 0; r < k; r++) s += v[r];
  let melhor = s;
  for (let r = k; r < v.length; r++) {
    s += v[r] - v[r - k];
    melhor = Math.max(melhor, s);
  }
  return melhor;
}

Com 1 milhão de leituras e janela de 1.000, a primeira versão faz cerca de 1 bilhão de somas; a segunda, 2 milhões.

Em resumo

Exercícios

Responda e confira na hora. Complexidades valem com ou sem espaços, como O(n log n).

  1. Em [1, 2, 4, 7, 11, 15], quais dois números somam 18? Responda como "7 e 11".

    Ver a solução

    Resposta: 7 e 11. L = 1, R = 15: 16 (L anda); 2 + 15 = 17 (L anda); 4 + 15 = 19 (R volta); 4 + 11 = 15 (L anda); 7 + 11 = 18.

  2. Qual a maior soma de 3 elementos seguidos em [2, 1, 5, 1, 3, 2]?

    Ver a solução

    Resposta: 9. Janelas: 2+1+5 = 8, 1+5+1 = 7, 5+1+3 = 9, 1+3+2 = 6. A maior é 9.

  3. Qual a complexidade da janela deslizante, em que cada elemento entra e sai da janela uma vez?

    Ver a solução

    Resposta: O(n). R avança n vezes e L avança no máximo n vezes: 2n passos, O(n).

Perguntar à IA

Monte um prompt pronto sobre Dois ponteiros e janela deslizante na sua linguagem e no seu caso, e abra num chat gratuito.

ChatGPT Claude Perplexity

O prompt vai para o site que você escolher. Não cole senhas, tokens nem dados reais de clientes. Para Gemini e outros, copie e cole.

Referências

Continue aprendendo

Todos os temas de algoritmos e estruturas de dados →