Suppose you are given an array of unsorted integers as
A = {3,4,5,1,4,2}
Input : 6
Output : {5,1}, {4,2}
My little answer about this problem for O(n) complexity with O(n) additional memory. This code snippet returns all unique indices pair of elements with sum K.
/**
* Returns indices of all complementary pairs in given {@code arr} with factor {@code k}. Two elements {@code arr[i]} and {@code arr[j]} are
* complementary if {@code arr[i] + arr[j] = k}.
* Method returns set of pairs in format {@literal [i,j]}. Two pairs {@literal [i,j]} and {@literal [j,i]} are treated as same, and only one pair
* is returned.
* Method support negative numbers in the {@code arr}, as wel as negative {@code k}.
*
* Complexity of this method is O(n) , requires O(n) additional memory.
*
* @param arr source array
* @param k factor number
* @return not {@code null} set of all complementary pairs in format {@literal [i,j]}
*/
public static Set getComplementaryPairs(int[] arr, int k) {
if (arr == null || arr.length == 0)
return Collections.emptySet();
Map> indices = new TreeMap<>();
for (int i = 0; i < arr.length; i++) {
if (!indices.containsKey(arr[i]))
indices.put(arr[i], new TreeSet<>());
indices.get(arr[i]).add(i);
}
Set res = new LinkedHashSet<>();
for (Map.Entry> entry : indices.entrySet()) {
int x = entry.getKey();
int y = k - x;
if (x == y) {
int size = entry.getValue().size();
if (size < 2)
continue;
Integer[] ind = entry.getValue().toArray(new Integer[size]);
for (int j = 0; j < size - 1; j++)
for (int m = j + 1; m < size; m++)
res.add(String.format("[%d,%d]", ind[j], ind[m]));
} else if (x < y && indices.containsKey(y))
for (int j : entry.getValue())
for (int m : indices.get(y))
res.add(String.format("[%d,%d]", j, m));
}
return res;
}