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

O(n)C++1767 lines2 examples

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

Example 1

Input

8 10
1 2 3 4 6 7 8 9

Expected output

4
1 9
2 8
3 7
4 6
Example 2

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.

doi-pointeri-perechi-suma-x.cpp
/*
 * 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.