Grade 12 · Advanced techniques: two pointers, binary search on the answer, monotonic stacksCitește în română
Two pointers: pairs with sum x in a sorted array
Original: Doi pointeri — perechi cu suma x într-un vector sortat
The idea
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.
Original description (Romanian)
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.
- Complexity
- O(n)
- Grade
- Grade 12 (Clasa a XII-a)
Examples
Input
8 10 1 2 3 4 6 7 8 9
Expected output
4 1 9 2 8 3 7 4 6
Input
3 100 1 2 3
Expected output
0
The code
Comments are in Romanian, as in the original collection. Edit freely: you can reset at any time.
/*
* 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;
}
Runs on a real g++ (C++17, -O2) through Compiler Explorer. Keep runs short; there's a time limit.