选择算法找到中间,元素向左和向右

时间:2012-04-13 02:42:12

标签: algorithm

假设我有一个大小为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步。我有以下疑虑:

  1. 我选择了正确的算法,它是否真的适用于我的程序的线性时间。我有点困惑,因为它类似于快速排序。
  2. 从主函数调用函数选择时,left,right和k的值是多少。考虑我的数组是列表[1 ... N]。
  3. 我是否必须调用选择功能三次,一次查找n / 2次最小值,另一次查找n / 2 + 1次最小值和另一次查找n / 2-1th最小值,或者可以完成一次通话,如果是,怎么样?
  4. 同样在功能选择(第三步)“选择左右之间的pivotIndex”中,我应该为我的程序/目的选择pivotIndex的值。
  5. 谢谢!

1 个答案:

答案 0 :(得分:2)

它就像快速排序,但它是线性的,因为在快速排序中,您需要同时处理枢轴的左侧和右侧,而在快速选择中,您只需处理一侧。

如果Select(A, 0, N, (N-1)/2)为奇数,则初始调用应为N;如果N是偶数,你需要确切地决定你想做什么。

要找到中间值和左/右,您可能想要调用它来查找中位数,然后只需将数组的最大组成部分放在左边,将组件的最小值放到右边,因为你知道一旦中位选择阶段完成,中位数左边的所有元素都将小于它,而右边的元素将更大(或相等)。这是O(n)+ n / 2 + n / 2 = O(n)总时间。

有很多方法可以选择枢轴指数。对于临时目的,中间元素或随机索引可能就足够了。