假设我有一组数字。我需要计算给定范围内的数量。
例如:对于给定集:{3, 4, 7, 10, 15, 30}
:
numbers in range (0, 6) = 2
numbers in range (8, 40) = 3
numbers in range (0, 50) = 6
什么样的结构最适合这个目的?最好的意思是指具有最快执行所述操作的结构。此外,快速插入和移除也将受到赞赏...
答案 0 :(得分:7)
如果您给出的数字集永远不会改变,一个简单的选项是按升序对数字进行排序,然后在范围的端点上使用binary search来确定排序序列中第一个元素的位置是否包含在范围内,并且第一个元素不在范围内。然后,您可以减去这两个位置的差异,以计算范围内的元素数量,或者只是迭代该范围以确定该范围内的所有数字。使用快速排序算法(如快速排序或堆栈),排序可以在O(n log n)时间内完成,每个查询只需要时间O(log n)进行两次不同的二进制搜索。
您可以通过各种方式加快速度。例如,如果您知道数字或多或少均匀分布,则可以使用interpolation search而不是二进制搜索来执行查找。这需要花费预期时间O(log log n)来执行每个查询,这比以前快得多。如果您知道这些数字都在[0,N]范围内,那么您可以使用更高级的数据结构,如van Emde Boas tree,以便在最坏的情况下将所有操作加速到O(log log N)。 / p>
另一方面,如果数字集可以增长和缩小,那么您可能需要考虑使用平衡二叉搜索树来存储数字。然后,您可以在树上进行有效搜索(在时间O(log n)中)以确定范围中的第一个数字和不在范围内的第一个数字。
希望这有帮助!
答案 1 :(得分:3)
这是计算几何中研究得很好的问题,它被称为range searching。虽然你有1-D版本。问题是每个操作有多常见,如果插入和删除很少,那么你可以将它们制成表格。这将为您提供O(n ^ 2)存储和恒定时间查询。
答案 2 :(得分:2)
如果您的数据集不会随着时间的推移而改变,那么templatetypedef的答案很好,但您提到需要快速插入和删除。 [编辑:David Eisenstat解释了对每个节点计数增加的平衡二叉树的两次O(log n)搜索如何有效地计算给定范围内的元素。]
在任何情况下,如果需要快速更新,您问题的理想数据结构是 Fenwick tree或BIT树。此数据结构为以下两个操作提供O(log n)保证:
两个查询调用允许您使用count(j) - count(i)
计算任何给定范围[i,j]中的元素数。
Fenwick树上的查询和更新都只涉及简单的按位操作和单个数组上的查找,因此使用此数据结构将在O(log n)上产生非常有竞争力的常量 - 我预计它将比在更新下维护一个平衡的二叉树,这需要指针操作和树重新平衡。
答案 3 :(得分:1)
这有什么问题?
static int Count(IList<int> set, int min, int max)
{
int count = 0;
foreach (int i in set)
if (i < max && i > min)
count++;
return count;
}