假设我有一个大小为n的未排序数组A.
如何在线性时间内找到原始未排序列表中的n / 2,n / 2-1,n / 2 + 1最小元素?
我尝试在wikipedia中使用选择算法(基于分区的通用选择算法是我正在实现的)。
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)
但我还没有理解3或4步。我有以下疑虑:
谢谢!
答案 0 :(得分:2)
它就像快速排序,但它是线性的,因为在快速排序中,您需要同时处理枢轴的左侧和右侧,而在快速选择中,您只需处理一侧。
如果Select(A, 0, N, (N-1)/2)
为奇数,则初始调用应为N
;如果N
是偶数,你需要确切地决定你想做什么。
要找到中间值和左/右,您可能想要调用它来查找中位数,然后只需将数组的最大组成部分放在左边,将组件的最小值放到右边,因为你知道一旦中位选择阶段完成,中位数左边的所有元素都将小于它,而右边的元素将更大(或相等)。这是O(n)+ n / 2 + n / 2 = O(n)总时间。
有很多方法可以选择枢轴指数。对于临时目的,中间元素或随机索引可能就足够了。