Two-sum
Abridged problem statement
Given a list () of numbers and a number , find distinct indices and such that , if they exist.
Solution
A naive solution would iterate over all pairs of values. However, after fixing one of the indices (), it is straightforward to realise that we must find such that and .
Then, we can store pairs in a sorted vector and use std::lower_bound to find where a given value appears.
Please elaborate!
Pairs are sorted lexicographically. So, for example, if our array was , then our array of pairs would be . This, sorted, is .
Notice that all occurences of equal values are grouped together. In addition to this, in a group of equal values, indices are sorted ascendingly. This is why we can use binary search to find the first occurence of a given value .
For further context, read this.
Code
#include <bits/stdc++.h>
using namespace std;
int main() {
int n, x;
cin >> n >> x;
vector<int> a(n);
for (int &i : a) {
cin >> i;
}
vector<pair<int, int>> buf;
for (int i = 0; i < n; ++i) {
buf.push_back({a[i], i});
}
sort(buf.begin(), buf.end());
for (int i = 0; i < n; ++i) {
int v = x - a[i];
pair<int, int> p = {v, -1};
auto it = lower_bound(buf.begin(), buf.end(), p);
if (it == buf.end() || it->first != v || it->second == i) {
continue;
}
cout << it->second + 1 << ' ' << i + 1 << '\n';
return 0;
}
cout << "IMPOSSIBLE\n";
}We use because we wish to find the first occurence of in . Setting the second element in the pair as ensures that we are smaller than any other pair that actually exists in buf, which makes std::lower_bound work correctly.
The time complexity of this code is , and its space complexity is .
Notes
- It is also possible to solve this problem using
std::map; this solution involves mapping a value to index map and also checking if exists among , same as our solution. - You can also use an incremental pointer to move along
bufif you process values in ascending order, but this is slightly more complicated and does not change the asymptotic complexity, as sorting still incurs .