查找范围内元素数量的最快方法
Fastest way to find number of elements in a range
给定一个带有n elements
的数组,如何找到在给定范围内index i to index j
O(log n)
或better
复杂度greater
或equal
给定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 处理具有多个线程的子范围,前提是它们足够厚实)来调整它。
在您的情况下,您的要求似乎很严格,因此后者似乎是借助探查器的最佳选择。
- 在 C++20 计算范围内相邻对的最简洁明了的方法是什么?
- 有什么方法可以将指针指向孩子范围内的父母(派生)班级
- 找到范围内素数的最快方法是什么
- 有没有一种标准方法来确保一段代码在全局范围内执行
- 在一定范围内检查公差相等性的最快方法
- 查找范围内元素数量的最快方法
- 模板类的方法使用全局范围内的 typedef.编译器错误
- 内联是否将函数/方法限制在其当前源文件的范围内
- 检查长类型数据是否在 int 范围内的便携式方法是什么?
- HSV和范围内方法无法正常工作
- 在全局范围内调用静态方法
- 在类范围内获取虚方法的类型
- 在一个范围内查找素数的直观方法
- c++检查范围内值的通用方法
- 在越来越多的坐标范围内运行prim的最快方法
- 错误:方法未在此范围内声明(但已包含)
- <<方法名称>>未在此范围内声明私有静态方法
- <<方法名称>>"未在此范围内声明
- C++:获取范围内整数的最快方法
- 测试值是否在阈值范围内的最佳方法(性能方面)是什么