You can find the median by finding the average between the floor(n/2)th largest item and the floor(n/2)th smallest item. This can be done with help of this previous SO question.
After that, simply iterate through your array, putting elements greater than the median into one and lower than the median into the other.
Alternatively, if you knew the size of your sequence, you could create two collections of size floor(n/2): one "smallest half" (S) and one "largest half" (L), and then one by one by one:
- Take out one element in your sequence, call it e.
- Put it into S if S is not full.
- If S is full, find the largest element of (S | e) (the union of the two) (this can be impelemented by iterating through S until an element larger than e is found; if none is found, it is e, else, it is the found element), and add it to L. If this largest was in S, put e in S to re-fill it.
- If L is full, find the smallest element of (L | e) and remove it, adding e into L if e was not removed.
I believe this is O(n) time; someone correct me if I'm wrong. The worst case scenario I could imagine is the original sequence being sorted in descending order.
ruby implementation (with much un-performancy shortcuts):
def split_into_halves to_split
s = []
l = []
medianlimit = to_split.size/2
for e in to_split
if s.size < medianlimit
s.push(e)
else
if s.max >= n
max = s.max
s.delete max
s.push(e)
else
max = e
end
if l.size < medianlimit
l.push(max)
elsif l.max >= max
l.delete l.max
l.push(max)
end
end
end
return [s,l]
end
k = [2,3,6,7,1,4,5]
split_into_halves(k) #=> [[2,3,1],[6,4,5]]