DSA sheet / Sorting and searching

Sum of Two Values

easy about 15 min Two pointerssortinghashingtwo-sum
Open on CSES

Do these first: Apartments

The problem in brief

Given an array of n integers (n up to 200 000) and a target x, print the positions (1-indexed) of two different elements whose values sum to x. If no such pair exists print IMPOSSIBLE. Any valid pair is accepted.

Try it

Tab indents; press Esc, then Tab, to leave the box. Ctrl+Enter runs.

Hints

Stuck? Reveal one hint at a time. Each nudges without giving away the next.

The walkthrough

Spoilers ahead: open a section only after you have given the hints a fair try.

How to think

The naive O(n^2) approach tries every pair. The improvement comes from reframing: for each a[i], the only acceptable partner is x - a[i], and “find a specific value” is a lookup problem. A hash map makes it expected O(1) per element; a sorted array makes it O(log n).

The two-pointer variant is even neater once the array is sorted. If the smallest plus the largest is too small, the smallest can never help (every other partner is even smaller), so drop it; if too large, drop the largest. Each step discards an element, so the sweep is linear. Because sorting scrambles positions, sort pairs of (value, original index) or sort indices by value.

The habit: whenever you are asked for a pair with a sum/difference condition, think “fix one, look up the other” or “sort and squeeze from both ends”.

Intuition

Line the numbers up small to large and put a finger on each end. If the two fingers add to less than the target you need bigger numbers, so move the left finger right; if they add to more, move the right finger left. They meet if no pair exists.

Approach
  1. Build a list of indices 0..n-1 sorted by value.
  2. Set l = 0, r = n - 1. While l < r: let s = a[idx[l]] + a[idx[r]]. If s == x, print idx[l] + 1 and idx[r] + 1 and stop. If s < x, l += 1; otherwise r -= 1.
  3. If the loop ends without a match, print IMPOSSIBLE.

Pitfalls: the sum of two values can reach 2 * 10^9 (over a 32-bit int), so add as 64-bit; the two positions must differ (guaranteed here by l < r even when two values are equal); output positions are 1-based.

Complexity

O(n log n) for the sort and O(n) for the sweep; O(n) memory.

Solutions

Written from scratch and checked by compiling and running each one against a brute force on random inputs. Fast input/output, the way you would submit it.

Show solutions (C++17, Python 3, Java 17, Node.js)
#include <bits/stdc++.h>
using namespace std;

int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    int n;
    long long x;
    cin >> n >> x;
    vector<pair<long long, int>> a(n);
    for (int i = 0; i < n; i++) {
        cin >> a[i].first;
        a[i].second = i + 1;
    }
    sort(a.begin(), a.end());
    int l = 0, r = n - 1;
    while (l < r) {
        long long s = a[l].first + a[r].first;
        if (s == x) {
            cout << a[l].second << " " << a[r].second << "\n";
            return 0;
        }
        if (s < x) l++;
        else r--;
    }
    cout << "IMPOSSIBLE\n";
    return 0;
}

Problem: CSES Problem Set (Antti Laaksonen, University of Helsinki), CC BY-NC-SA 4.0. The explanations and code above are original (© Anupam Kumar).

Related problems

Back to the sheet