There is a randomized algorithm able to accomplish this task in O(n)
steps (average case scenario), but it does involve sorting some subsets of the array. And, because of its random nature, there is no guarantee it will actually ever finish (though this unfortunate event should happen with vanishing probability).
I will leave the main idea here. For a more detailed description and for the proof of why this algorithm works, check here.
Let A
be your array and let n=|A|
. Lets assume all elements of A
are distinct. The algorithm goes like this:
- Randomly select
t = n^(3/4)
elements from A
.
- Let
T
be the "set" of the selected elements.Sort T
.
- Set
pl = T[t/2-sqrt(n)]
and pr = T[t/2+sqrt(n)]
.
- Iterate through the elements of
A
and determine how many elements are less than pl
(denoted by l
) and how many are greater than pr
(denoted by r
). If l > n/2
or r > n/2
, go back to step 1.
- Let
M
be the set of elements in A
in between pl
and pr
. M
can be determined in step 4, just in case we reach step 5. If the size of M
is no more than 4t
, sort M
. Otherwise, go back to step 1.
- Return
m = M[n/2-l]
as the median element.
The main idea behind the algorithm is to obtain two elements (pl
and pr
) that enclose the median element (i.e. pl
< m
< pr
) such that these two are very close one two each other in the ordered version of the array (and do this without actually sorting the array). With high probability, all the six steps only need to execute once (i.e. you will get pl
and pr
with these "good" properties from the first and only pass through step 1-5, so no going back to step 1). Once you find two such elements, you can simply sort the elements in between them and find the median element of A
.
Step 2 and Step 5 do involve some sorting (which might be against the "rules" you've mysteriously established :p). If sorting a sub-array is on the table, you should use some sorting method that does this in O(slogs)
steps, where s
is the size of the array you are sorting. Since T
and M
are significantly smaller than A
the sorting steps take "less than" O(n)
steps. If it is also against the rules to sort a sub-array, then take into consideration that in both cases the sorting is not really needed. You only need to find a way to determine pl
, pr
and m
, which is just another selection problem (with respective indices). While sorting T
and M
does accomplish this, you could use any other selection method (perhaps something rici suggested earlier).