Clasa a XII-a · Tehnici avansate: doi pointeri, căutare binară pe răspuns, stive monotoneRead in English
Doi pointeri — perechi cu suma x într-un vector sortat în C++
În engleză: Two pointers: pairs with sum x in a sorted array
Ideea
Vectorul are n valori distincte, în ordine strict crescătoare. Vrem perechile de poziții i < j cu a[i] + a[j] = x. În loc să încercăm toate cele n * (n-1) / 2 perechi, punem un indice st la început și unul dr la sfârșit. Dacă a[st] + a[dr] < x, suma trebuie să crească, deci st++; dacă e mai mare, dr--; dacă e egală, am găsit o pereche și mutăm ambii indici. Fiecare pas mută cel puțin un indice spre celălalt, deci sunt cel mult n pași. Afișăm numărul perechilor, apoi perechile.
Descrierea în engleză
The array has n distinct values in strictly increasing order. We want the position pairs i < j with a[i] + a[j] = x. Instead of trying all n * (n-1) / 2 pairs, we put an index st at the beginning and one dr at the end. If a[st] + a[dr] < x, the sum must grow, so st++; if it is larger, dr--; if it is equal, we found a pair and move both indices. Every step moves at least one index towards the other, so there are at most n steps. We print the number of pairs, then the pairs.
- Complexitate
- O(n)
- Clasa
- Clasa a XII-a (Grade 12)
Exemple
Intrare
8 10 1 2 3 4 6 7 8 9
Ieșire așteptată
4 1 9 2 8 3 7 4 6
Intrare
3 100 1 2 3
Ieșire așteptată
0
Codul C++
Codul complet, cu comentarii în română. Îl poți modifica liber și îl poți reseta oricând.
/*
* Titlu: Doi pointeri — perechi cu suma x într-un vector sortat
* Clasa: 12
* Capitol: Tehnici avansate: doi pointeri, căutare binară pe răspuns, stive monotone
* Descriere: Vectorul are n valori distincte, în ordine strict crescătoare. Vrem
* perechile de poziții i < j cu a[i] + a[j] = x. În loc să încercăm
* toate cele n * (n-1) / 2 perechi, punem un indice st la început și
* unul dr la sfârșit. Dacă a[st] + a[dr] < x, suma trebuie să crească,
* deci st++; dacă e mai mare, dr--; dacă e egală, am găsit o pereche
* și mutăm ambii indici. Fiecare pas mută cel puțin un indice spre
* celălalt, deci sunt cel mult n pași. Afișăm numărul perechilor, apoi
* perechile.
* Complexitate: O(n)
*
* Exemplu
* Intrare:
* 8 10
* 1 2 3 4 6 7 8 9
* Ieșire:
* 4
* 1 9
* 2 8
* 3 7
* 4 6
*
* Exemplu
* Intrare:
* 3 100
* 1 2 3
* Ieșire: 0
*/
#include <iostream>
#include <utility>
#include <vector>
using namespace std;
int main()
{
int n;
long long x;
cin >> n >> x;
vector<long long> a(n);
for (int i = 0; i < n; i++)
cin >> a[i];
vector<pair<long long, long long>> perechi;
int st = 0, dr = n - 1;
while (st < dr)
{
long long s = a[st] + a[dr];
if (s < x)
st++;
else if (s > x)
dr--;
else
{
perechi.push_back({a[st], a[dr]});
st++;
dr--;
}
}
cout << perechi.size() << '\n';
for (auto &p : perechi)
cout << p.first << ' ' << p.second << '\n';
return 0;
}
Rulează pe un g++ adevărat (C++17, -O2) prin Compiler Explorer. Programele trebuie să se termine repede: există o limită de timp.