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

Fastest way to find number of elements in a range

本文关键字:方法 范围内 元素 查找      更新时间:2023-10-16

给定一个带有n elements的数组,如何找到在给定范围内index i to index jO(log n)better复杂度greaterequal给定value (x)的元素数?

我的实现是这个,但它是O(n)

for(a=i;a<=j;a++)
if(p[a]>=x) // p[] is array containing n elements
count++;

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

两个想法:

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

2) 使用持久*平衡订单统计二叉树,它维护树的 n 个版本,版本 i 是通过向其添加 a[i] 从版本 i-1 形成的。要回答query([0,i], x),你查询版本 i 树以获取> x元素的数量(基本上是排名信息)。订单统计树可让您执行此操作。

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

如果数组已排序,则可以通过二叉搜索找到小于 X 的第一个值,大于 X 的元素数是该元素之后的项目数。那将是O(log(n))。

如果数组没有排序,则无法在少于 O(n) 的时间内完成排序,因为您必须检查每个元素以检查它是否大于或等于 X。

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

这方面的标准算法基于快速排序的分区,有时称为快速选择

这个想法是,您不对数组进行排序,而只是对包含 x 的部分进行分区,并在 x 是您的枢轴元素时停止。该过程完成后,所有元素 x 和更大的元素都在 x 的右侧。此过程与查找第 k 个最大元素的过程相同。

阅读一个非常类似的问题 如何在 O(n) 中长度为 n 的未排序数组中找到第 k 个最大的元素?。

需求索引 i 到 j不是给问题带来任何复杂性的限制。

考虑到数据没有提前排序并在查询之间不断变化的要求,O(n) 是您希望达到的最佳复杂性,因为如果不查看所有元素,就无法计算大于或等于某个值的元素数。

如果您考虑一下,这相当简单:如果您不知道如何提前表示/排序,则无法避免检查任何类型的搜索范围的每个元素。

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

所以这里的O(N)实际上没有任何问题。这是理想的情况,您正在考虑要么更改外部涉及的数据的整个性质,以允许提前对其进行有效排序,要么进行微优化(例如:并行 fors 处理具有多个线程的子范围,前提是它们足够厚实)来调整它。

在您的情况下,您的要求似乎很严格,因此后者似乎是借助探查器的最佳选择。