Here's a little solution that took me a while to cook. It's pretty tricky to get right, but I do believe this was good effort towards a highly optimized machine for solution (C++0x, compiles well with Visual Studio 2010, I bet gcc would breathe through as well):
PS: It's long because I painstakingly decided to write up something close to asymptotic optimal performance.
The basic idea is to start a binary search for the the first number equal to or larger than the sum divided by two.
- If that number is found (which if multiplied by two gives the sum), it will be handled as a special case.
- Otherwise
a - do a binary search for the complement of that number. (If found, add the counts by multiplication and some additional binary searches for counting).
b - If not found, seed a new value for a "higher" value, using the current "lower" value.
Repeat till all numbers are considered.
There's still a bug with negative numbers, I think. [edit]Just confirmed that it does not mess up with negatives[/edit]
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
int count_pairs_equal_to_sum(vector<int> v, int sum){
int count = 0;
sort(v.begin(), v.end());
auto upper = lower_bound(v.begin(), v.end(), sum / 2);
if(*upper * 2 == sum){
auto upper_next = upper_bound(upper, v.end(), *upper);
auto n = upper_next - upper;
count += n*(n-1)/2;
upper = upper_next;
}
auto bottom = upper;
while(upper != v.end()){
auto bottom_prev = bottom;
bottom = lower_bound(v.begin(), bottom, sum - *upper);
if(*upper + *bottom == sum){
count += (upper_bound(bottom, bottom_prev, *bottom) - bottom) * (upper_bound(upper, v.end(), *upper) - upper);
}
if(bottom == v.begin()){
return count;
}
upper = lower_bound(upper, v.end(), sum - *(bottom-1));
}
return count;
}
int main(){
int arr[] = {0, 1, 2, 2, 3, 4, 5, 6, 7, 8, 9, 10};
vector<int> v(arr, arr+sizeof(arr)/sizeof(int));
cout << count_pairs_equal_to_sum(v, 8) << endl;
return 0;
}
Note: There's still some ironing in progress. I found some boogies in the results. [edit2]Ok, corrected. Forgot to safe guard with a return if we never enter into the while loop.[/edit2]