Skip to main content

Fast Median

NO need to sort all the items. Just find the sort the items before the median index Using quicksort, find the partition. Then throw away the left partition if the median index lies in the right portion while calibrating the new median index.

Similar to finding the kth smallest item in the unsorted list

package algorithmdesignmanualbook.sorting

import utils.shouldBe

/**
* NO need to sort all the items.
* Just find the sort the items before the median index
* Using quicksort, find the partition.
* Then throw away the left partition if the median index lies in the right portion
* while calibrating the new median index.
*
* Similar to finding the kth smallest item in the unsorted list
*/
private fun fastMedian(array: IntArray, low: Int, high: Int, medianIndex: Int): Int {
val j = partition(array, low, high)
return if (j - low == medianIndex) {
array[j]
} else if (j - low > medianIndex) {
fastMedian(array, low, j - 1, medianIndex)
} else {
fastMedian(array, j + 1, high, medianIndex - j - 1 + low)
}
}

private fun quickSort(array: IntArray, low: Int, high: Int) {
if (low < high) {
val j = partition(array, low, high)
quickSort(array, low, j)
quickSort(array, j + 1, high)
}
}

private fun partition(array: IntArray, low: Int, high: Int): Int {
fun swap(index1: Int, index2: Int) {
val temp = array[index1]
array[index1] = array[index2]
array[index2] = temp
}

val pivot = array[low]
var i = low
var j = high

do {
while (array[i] <= pivot) i++
while (array[j] > pivot) j--
if (i < j) swap(i, j)
} while (i < j)
swap(low, j)
return j
}

fun midpointIndex(array: IntArray): Int {
return (array.size / 2)
}

fun main() {
run {
val original = intArrayOf(9, 1, 0, 2, 3, 4, 6, 8, 7, 10, 5)
val expected = original.sorted().toIntArray()
val quickSortInput = original.clone()
quickSort(quickSortInput, 0, original.lastIndex)
quickSortInput shouldBe expected

fastMedian(original, 0, original.lastIndex, midpointIndex(original)) shouldBe 5
}

run {
val original = intArrayOf(-90, 11, 30, 44, 20, 12, 22, -10, 1, 8, 90, 7, 10)
fastMedian(original, 0, original.lastIndex, midpointIndex(original)) shouldBe 11
}
}


Updated on 2021-09-11