Suppose I had an unsorted array A of size n.
How to find the n/2, n/2−1, n/2+1th smallest element from the original unsorted list in linear time?
I tried to use the selection algorithm in wikipedia (Partition-based general selection algorithm is what I am implementing).
function partition(list, left, right, pivotIndex)
pivotValue := list[pivotIndex]
swap list[pivotIndex] and list[right] // Move pivot to end
storeIndex := left
for i from left to right-1
if list[i] < pivotValue
swap list[storeIndex] and list[i]
increment storeIndex
swap list[right] and list[storeIndex] // Move pivot to its final place
return storeIndex
function select(list, left, right, k)
if left = right // If the list contains only one element
return list[left] // Return that element
select pivotIndex between left and right //What value of pivotIndex shud i select??????????
pivotNewIndex := partition(list, left, right, pivotIndex)
pivotDist := pivotNewIndex - left + 1
// The pivot is in its final sorted position,
// so pivotDist reflects its 1-based position if list were sorted
if pivotDist = k
return list[pivotNewIndex]
else if k < pivotDist
return select(list, left, pivotNewIndex - 1, k)
else
return select(list, pivotNewIndex + 1, right, k - pivotDist)
But I have not understood 3 or 4 steps. I have following doubts:
- Did I pick the correct algorithm and will it really work in linear time for my program. I am bit confused as it resembles like quick sort.
- While Calling the Function Select from the main function, what will be the value of left, right and k. Consider my array is list [1…N].
- Do I have to call select function three times, one time for finding n/2th smallest, another time for finding n/2+1 th smallest and one more time for n/2-1th smallest, or can it be done on a single call, if yes, how?
- Also in function select (third step) “select pivotIndex between left and right”, what value of pivotIndex should I select for my program/purpose.
Thanks!
It is like quicksort, but it’s linear because in quicksort, you then need to handle both the left and right side of the pivot, while in quickselect, you only handle one side.
The initial call should be
Select(A, 0, N, (N-1)/2)ifNis odd; you’ll need to decide exactly what you want to do ifNis even.To find the median and left/right, you probably want to call it to find the median, and then just do the max of the components of the array to the left and the min of the components to the right, because you know once the median selection phase is done that all elements to the left of the median will be less than it and to the right will be greater (or equal). This is O(n) + n/2 + n/2 = O(n) total time.
There are lots of ways to choose pivot indices. For casual purposes, either the middle element or a random index will probably suffice.