Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Two pairs of numbers with same sum

Given a list [a_1 a_2 ... a_n] of (not necessarily distinct) integers, determine whether there exist pairwise distinct indices w,x,y,z such that a_w + a_x = a_y + a_z.

I know that one way is to use 4 levels of for loops, each one iterating over one of the indices. When we get equal sums, check whether all the indices are pairwise distinct. If they are, return true. If we've exhausted all the possibilities, return false. This has running time O(n^4).

Can we do better?

like image 648
John Avatar asked Oct 12 '12 16:10

John


2 Answers

Compute all possible values for a_w + a_x, insert them to hash table. Insert (a_w + a_x, w) and (a_w + a_x, x) to second hash table.

Prior to inserting a value to first hash table, check if it is already in the table. If so, check second table. If either of (a_w + a_x, w) or (a_w + a_x, x) is there, don't insert anything (we've got a duplicate element). If neither of these pairs is in the second table, we've got positive answer.

If, after processing all (w, x) pairs, we've got no positive answer, this means there is no such pairwise distinct indices.

Time complexity is O(n2). Space requirements are also O(n2).

It is possible to do the same in O(n) space but O(n2 * log(n)) time with slightly modified algorithm from this answer: Sum-subset with a fixed subset size:

  1. Sort the list.
  2. Use a priority queue for elements, containing a_w + a_x as a key and w, x as values. Pre-fill this queue with n-1 elements, where x = 0 and w = 1 .. n-1.
  3. Repeatedly pop minimal element (sum, w, x) from this queue and put element (a_w + a_x_plus_1, w, x+1) to the queue (but don't put elements when x >= w). Stop when two consecutive elements, removed from queue, have the same sum.
  4. To handle duplicates, it is possible to compare w, x of two consecutive elements, having equal sum. But it's easier to use krjampani's idea of pre-processing. If sorted list contains two pairs of duplicates or a single element is duplicated 4 times, success. Otherwise no more than a single value is duplicated; leave only single instance of it in the list and add its doubled value into priority queue along with a "special" pair of indexes: (2a, -1, -1).
like image 68
Evgeny Kluev Avatar answered Oct 10 '22 04:10

Evgeny Kluev


Evgeny's solution can be some what simplified by preprocessing the original array as follows.

We first use a hash table to count the frequency of each element in the original array. If at least 2 elements have duplicates (their frequency is at least 2) or if an element occurs with frequency at least 4 the answer is true. Otherwise, if an element a occurs with frequency 2 or 3, we add 2a to a second hash table, and replace all copies of a with a single copy in the original array.

Then in the modified array, for each pair of indices i, j with i < j, we add a_i + a_j to the second hash table and return true if we find a duplicate entry in this hash table.

like image 37
krjampani Avatar answered Oct 10 '22 03:10

krjampani