有效地查找未排序列表前缀的顺序统计信息?

时间:2013-03-12 01:46:39

标签: algorithm data-structures language-agnostic

A是从1n的整数数组,按随机顺序排列。

我至少需要在日志时间内随机访问第一个i元素的j个最大元素。

到目前为止,我提出的是n x n矩阵M,其中(i, j)位置的元素是第一个i中最大的元素{ {1}}。这为我提供了恒定时间随机访问,但需要j存储。

通过构造,n^2按行和列排序。此外,每列与其邻居的区别在于单个值。

有人可以建议使用M或更好的随机访问时间将M压缩到n log(n)空间或更好的方式吗?

2 个答案:

答案 0 :(得分:10)

我相信你可以在O(log(N))时间内执行访问,给定O(N log(N))预处理时间和O(N log(N))额外空间。这是怎么回事。

您可以扩充红黑树以支持select(i)操作,该操作在O(log(N))时间内检索排名i的元素。例如,see this PDF算法简介的相应章节。

您可以以功能方式实现红黑树(甚至可以增加一个以支持select(i)),以便insert操作返回一个新树,该树除了O(log(N))节点之外共享所有节点老树。例如,见Chris Okasaki的Purely Functional Data Structures

我们将构建一个纯函数增强红黑树的数组T,以便树T[j]存储0 ... j-1j元素的索引A {1}}从最大到最小排序。

基本情况:在T[0]创建一个只有一个节点的增强红黑树,其数据为数字0,它是数组前1个元素中第0个最大元素的索引{{ 1}}。

归纳步骤:对于从1到A的每个j,在N-1处通过纯函数插入索引为T[j]的新节点来创建增强的红黑树树j。这最多创建了O(log(j))个新节点;其余节点与T[j-1]共享。这需要O(log(j))时间。

构造数组T[j-1]的总时间是O(N log(N)),使用的总空间也是O(N log(N))。

创建T后,您可以通过执行T[j-1]来访问i元素的j元素中的A个最大元素。这需要O(log(j))时间。请注意,您可以在第一次需要时懒惰地创建T[j-1].select(i)。如果T[j-1]非常大且A总是相对较小,这将节省大量时间和空间。

答案 1 :(得分:3)

除非我误解,否则你只是找到一个数组的k-th order statistic,它是另一个数组的前缀。

这可以使用我认为称为“quickselect”的算法或沿着这些行的东西来完成。基本上,它就像快速排序:

  1. 随机转动
  2. 交换数组元素,使所有较小的元素都在一边
  3. 您知道这是第p + 1个最大元素,其中p是较小数组元素的数量
  4. 如果p + 1 = k,那就是解决方案!如果p + 1> k,重复'较小'子阵列。如果p + 1 < k,在较大的'子阵列'上重复。
  5. Quickselect和Quicker Select标题下有一个(很多)更好的描述here,如果你搜索k阶快速排序解决方案,通常也会在互联网上。

    虽然这个算法的最坏情况时间是像快速排序一样的O(n2),但如果你正确选择你的随机枢轴,它的预期情况要好得多(也像快速排序)。我认为空间复杂度只是O(n);你只需制作一个前缀副本就可以搞清楚。