We have three sets S1, S2, S3. I need to find x,y,z such that x E S1 y E S2 z E S3
let min denote the minimum value out of x,y,z let max denote the maximum value out of x,y,z The range denoted by max-min should be the MINIMUM possible value
We have three sets S1, S2, S3. I need to find x,y,z such that x E S1 y E S2 z E S3
let min denote the minimum value out of x,y,z let max denote the maximum value out of x,y,z The range denoted by max-min should be the MINIMUM possible value
min = infinity (really large number in practice, like 1000000000)
solution = (-, -, -)
for each x E S1
for each y E S2
for each z E S3
t = max(x, y, z) - min(x, y, z)
if t < min
min = t
solution = (x, y, z)
Of course, the full-bruteforce solution described by IVlad is simple and therefore, easier and faster to write, but it's complexity is O(n3)
.
According to your algorithm
tag, I would like to post a more complex algorithm, that has a O(n2)
worst case and O(nlogn)
average complexity (almost sure about this, but I'm too lazy to make a proof).
Algorithm description
Consider thinking about some abstract (X, Y, Z)
tuple. We want to find a tuple that has a minimal distance between it's maximum and minimum element. What we can say at this point is that distance is actually created by our maximum element and minimum element. Therefore, the value of element between them really doesn't matter as long as it really lies between the maximum and the minimum.
So, here is the approach. We allocate some additional set (let's call it S
) and combine every initial set (X
, Y
, Z
) into one. We also need an ability to lookup the initial set of every element in the set we've just created (so, if we point to some element in S
, let's say S[10]
and ask "Where did this guy come from?", our application should answer something like "He comes from Y
).
After that, let's sort our new set S
by it's keys (this would be O(n log n) or O(n) in some certain cases)
Determining the minimal distance
Now the interesting part comes. What we want to do is to compute some artificial value, let's call it minimal distance and mark it as d[x]
, where x
is some element from S
. This value refers to the minimal max - min
distance which can be achived using the elements that are predecessors / successors of current element in the sequence.
Consider the following example - this is our S
set(first line shows indexes, second - values and letters X
, Y
and Z
refer to initial sets):
0 1 2 3 4 5 6 7
------------------
1 2 4 5 8 10 11 12
Y Z Y X Y Y X Z
Let's say we want to compute that our minimal distance for element with index 4. In fact, that minimal distance means the best (x, y, z)
tuple that can be built using the selected element.
In our case (S[4]
), we can say that our (x, y, z)
pair would definitely look like (something, 8, something)
, because it should have the element we're counting the distance for (pretty obvious, hehe).
Now, we have to fill the gaps. We know that elements we're seeking for, should be from X
and Z
. And we want those elements to be the best in terms of max - min
distance. There is an easy way to select them.
We make a bidirectional run (run left, the run right from current element) seeking for the first element-not-from-Y
. In this case we would seek for two nearest elements from X
and Z
in two directions (4 elements total).
This finding method is what we need: if we select the first element of from X
while running (left / right, doesn't matter), that element would suit us better than any other element that follows it in terms of distance. This happens because our S
set is sorted.
In case of my example (counting the distance for element with index number 4
), we would mark elements with indexes 6
and 7
as suitable from the right side and elements with indexes 1
and 3
from the left side.
Now, we have to test 4 cases that can happen - and take the case so that our distance is minimal. In our particular case we have the following (elements returned by the previous routine):
Z X Y X Z
2 5 8 11 12
We should test every (X, Y, Z) tuple that can be built using these elements, take the tuple with minimal distance and save that distance for our element. In this example, we would say that (11, 8, 12)
tuple has the best distance of 4
. So, we store d[5] = 4
(5
here is the element index).
Yielding the result
Now, when we know how to find the distance, let's do it for every element in our S
set (this operation would take O(n2)
in the worst case and better time - something like O(nlogn)
in average).
After we have that distance value for every element in our set, just select the element with minimal distance and run our distance counting algorithm (which is described above) for it once again, but now save the (-, -, -)
tuple. It would be the answer.
Pseudocode
Here is comes the pseudocode, I tried to make it easy to read, but it's implementation would be more complex, because you'll need to code set lookups *("determine set for element"). Also note that determine tuple and determine distance routines are basically the same, but the second yields the actual tuple.
COMBINE (X, Y, Z) -> S
SORT(S)
FOREACH (v in S)
DETERMINE_DISTANCE(v, S) -> d[v]
DETERMINE_TUPLE(MIN(d[v]))
P.S
I'm pretty sure that this method could be easily used for (-, -, -, ... -) tuple seeking, still resulting in good algorithmic complexity.