查找范围内元素数量的最快方法

时间:2015-05-01 04:47:13

标签: java c++ algorithm

给定一个包含n elements的数组,如何查找给定范围greater中给定equal的{​​{1}}元素数量或value (x)元素数量index i to index jO(log n)复杂度?

我的实现是这样的,但它是better

O(n)

3 个答案:

答案 0 :(得分:2)

如果您被允许预处理数组,然后O(n log n)预处理时间,我们可以在[i,j]时间内回答任何O(log n)查询。

两个想法:

1)观察到能够回答[0,i][0,j]查询就足够了。

2)使用持久*平衡顺序统计二进制树,它维护树的n个版本,版本i由版本i-1通过向其添加[i]而形成。要回答query([0,i], x),请在版本i树中查询元素数> x(基本上是排名信息)。订单统计树可以让您这样做。

*:持久数据结构是一种优雅的函数式编程概念,适用于不可变数据结构,并具有高效的构造算法。

答案 1 :(得分:2)

O(log N)中不可能,因为您必须检查所有元素,因此需要O(N)方法。

此标准算法基于quicksort的分区,有时称为快速选择

这个想法是你不对数组进行排序,而只是对包含x的部分进行分区,并在x是你的pivot元素时停止。完成该过程后,您将x的所有元素设置为x和更大。这与找到第k个最大元素时的过程相同。

How to find the kth largest element in an unsorted array of length n in O(n)?了解非常类似的问题。

需求索引i到j 不是一个限制,会引入问题的任何复杂性。

答案 2 :(得分:0)

根据您的要求,数据未提前排序并且在查询之间不断变化,O(n)是您希望实现的最佳复杂性,因为无法计算大于或等于某些元素的数量不看所有的价值。

如果你仔细想想它就相当简单:如果你不知道它是如何预先表示/订购的,你就不能避免检查任何类型搜索范围的每个元素。

你可以动态构建一个平衡的二叉树,甚至是基数排序,但你只是将其他地方的开销推到相同的线性或更差的线性O(NLogN)复杂度,因为这样的算法再一次让你检查每个元素在范围内首先对它进行排序。

所以O(N)实际上并没有错。这是理想的,您正在考虑改变外部数据的整体性质,以便提前对其进行有效排序或微观优化(例如:并行处理具有多个线程的子范围,前提是它们“足够矮胖”来调整它。

在您的情况下,您的要求似乎很严格,因此后者在分析器的帮助下似乎是最好的选择。