You have an ascending list of numbers, what is the most efficient algorithm you can think of to get the ascending list of sums of every two numbers in that list. Duplicates in the resulting list are irrelevant, you can remove them or avoid them if you like.
To be clear, I'm interested in the algorithm. Feel free to post code in any language and paradigm that you like.
This question has been wracking my brain for about a day now. Awesome.
Anyways, you can't get away from the n^2 nature of it easily, but you can do slightly better with the merge since you can bound the range to insert each element in.
If you look at all the lists you generate, they have the following form:
(a[i], a[j]) | j>=i
If you flip it 90 degrees, you get:
(a[i], a[j]) | i<=j
Now, the merge process should be taking two lists
i
andi+1
(which correspond to lists where the first member is alwaysa[i]
anda[i+1]
), you can bound the range to insert element(a[i + 1], a[j])
into listi
by the location of(a[i], a[j])
and the location of(a[i + 1], a[j + 1])
.This means that you should merge in reverse in terms of
j
. I don't know (yet) if you can leverage this acrossj
as well, but it seems possible.The best I could come up with is to produce a matrix of sums of each pair, and then merge the rows together, a-la merge sort. I feel like I'm missing some simple insight that will reveal a much more efficient solution.
My algorithm, in Haskell:
I found a minor improvement, one that's more amenable to lazy stream-based coding. Instead of merging the columns pair-wise, merge all of them at once. The advantage being that you start getting elements of the list immediately.
However, if you know you're going to use all of the sums, and there's no advantage to getting some of them earlier, go with '
foldl merge []
', as it's faster.