假设我有一个大小为N的未排序数组A。
如何在线性时间内从原始未排序列表中找到N/2,N/21,N/2+1个最小元素?
我尝试使用维基百科中的选择算法(基于分区的通用选择算法就是我正在实现的)。
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个步骤我还没有理解。我有以下疑问:
谢啦!
它就像quicksort,但它是线性的,因为在quicksort中,你需要处理枢轴的左右两边,而在quickselect中,你只处理一边。
如果
要查找中值和left/right,您可能想调用它来查找中值,然后只需对左边的数组分量进行max,对右边的分量进行min,因为您知道一旦完成中值选择阶段,中值左边的所有元素将小于它,而右边的元素将大于它(或相等)。这是O(n)+n/2+n/2=O(n)总时间。
选择枢轴指标的方法有很多种。对于偶然的目的,中间元素或随机索引可能就足够了。