Two Pointers

Mediu~16 min20 pași

De ce contează?

Cauți două cărți pe un raft ordonat după grosime care, puse împreună, să aibă exact o anumită înălțime. Pui un deget la cea mai subțire și unul la cea mai groasă. Dacă suma e prea mare, muți degetul de sus spre cărți mai subțiri; dacă e prea mică, pe cel de jos spre mai groase. Te apropii din ambele capete.

Ideea: doi indici care se mișcă inteligent

Two pointers folosește doi indici care parcurg vectorul mișcându-se după o condiție, în loc să verifici toate perechile. Pe multe probleme transformă O(n²) în O(n). Funcționează des pe vectori sortați, unde mișcarea unui indice are efect previzibil asupra rezultatului.

Exemplu clasic: pereche cu sumă dată

Vector sortat {1, 3, 4, 6, 8, 11}, caut o pereche cu suma 10. st la început, dr la final:

stdrv[st]+v[dr]comparațiemișcare
051+11=12> 10dr--
041+8=9< 10st++
143+8=11> 10dr--
133+6=9< 10st++
234+6=10= 10găsit!
v
1
3
4
6
8
11
0
1
2
3
4
5
st
dr
Pornești cu st la cel mai mic și dr la cel mai mare. Suma prea mare → dr scade; suma prea mică → st crește. Indicii converg.

Implementare C++

#include <iostream>
using namespace std;

int main() {
    int v[] = {1, 3, 4, 6, 8, 11}, n = 6, tinta = 10;

    int st = 0, dr = n - 1;
    bool gasit = false;
    while (st < dr) {
        int suma = v[st] + v[dr];
        if (suma == tinta) { gasit = true; break; }
        else if (suma < tinta) st++;    // suma prea mica -> crestem st
        else dr--;                      // suma prea mare -> scadem dr
    }
    if (gasit) cout << v[st] << " + " << v[dr] << " = " << tinta << "\n";
    else cout << "nu exista pereche\n";
    return 0;
}
Observația-cheie

De ce funcționează: pe vector sortat, dacă suma e prea mică, singurul mod de a o mări e să crești st (spre valori mai mari). Dacă e prea mare, scazi dr. Niciun indice nu se întoarce, deci faci cel mult n pași.

Alte tipare two pointers

  • Eliminarea duplicatelor dintr-un vector sortat (un indice scrie, altul citește).
  • Interclasarea a doi vectori sortați (un indice per vector — vezi lecția dedicată).
  • Fereastra glisantă de lungime variabilă (capetele se mișcă independent).

Complexitate

MetodăTimpSpațiu
two pointersO(n)O(1)
toate perechileO(n²)O(1)

Pe vector nesortat, adaugă sortarea: O(n log n) o dată, apoi O(n).

Greșeli frecvente

Capcane reale la two pointers:

  • Vector nesortat: pentru pereche cu sumă, logica mișcării presupune sortare. Pe date nesortate dă rezultate greșite.
  • Condiția st < dr: cu st <= dr ai compara un element cu el însuși; cu mișcare greșită poți sări soluția.
  • Miști ambii indici deodată fără motiv: la majoritatea problemelor, doar unul se mișcă per pas, în funcție de comparație.
  • Buclă infinită: dacă pe vreo ramură niciun indice nu se mișcă, bucla nu se termină.

Vizualizare

Urmărește cum cei doi indici converg din capete în funcție de comparația cu ținta:

Indiciu

Observă că la fiecare pas se mișcă un singur indice — cel care apropie suma de țintă. Spațiul dintre st și dr se micșorează mereu, garantând oprirea.

De reținut

  • Two pointers = doi indici care se mișcă după o condiție, des pe vector sortat.
  • Suma prea mică → st++; prea mare → dr--; converg în O(n), nu O(n²).
  • Indicii nu se întorc niciodată → cel mult n pași; pe date nesortate, sortează întâi.

Întrebarea 1 / 3

Ce înseamnă tehnica „two pointers”?