Abusing the fact that no memory constrain is specified. And using the usual divide and conquer approach.
Number of all permutations for 4 number subsets is C(n,4) and is O(n^4). Number of all permutations for 2 numbers is C(n,2) and is O(n^2). O(n^2) seems to be OK for the task.
- Input is: an array
A
with n
elements, X
.
- Generate all permutations for 2 number subsets (that's O(n^2)) and put their sums into array
B
with n^2 elements (also remembering the subsets). Let's denote as S[B[i]]
the subset (consisting of the two numbers) whose sum is B[i]
.
- Sort the
B
, O(n^2*log(n^2)).
Walk through the array B
(O(n^2)) i = [0,n^2)
and quick search O(log(n^2)) = O(log(n))
in it for the value (X - B[i])
. There might be several of them (but not more than n^2).
4.1. Walk through all the elements with value of (X - B[i])
, using index k
.
4.2. Skip the elements B[k]
where S[B[k]]
intersects with S[B[i]]
. Intersection of two sets with two numbers can be calculated in O(1).
4.3 If k
is the index a element where B[i] + B[k] == X
and S[B[k]]
doesn't intersect with S[B[i]]
, then the sum of the sets S[B[k]]
and S[B[i]]
are the four sought numbers.
Performance is:
O( n^2 + n^2*log(n^2) + n^2*log(n^2) ) = O( n^2 * log(n^2) ) = O( n^2 * log(n) )
On step four, when we iterate over the multiple matching elements of B
using nested loop. Yet, total number of iterations of the two nested loops is limited by the |B|
which is O(n^2). The quick search is not the usual variation but the one which finds the matching element with the lowest index. (Alternatively one can use the usual bsearch
and since we might have landed in the middle, use two adjacent loops, checking elements in both directions.)