Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/337.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 用于确定特定范围内有多少元素的数据结构?_C#_Algorithm_Data Structures - Fatal编程技术网

C# 用于确定特定范围内有多少元素的数据结构?

C# 用于确定特定范围内有多少元素的数据结构?,c#,algorithm,data-structures,C#,Algorithm,Data Structures,假设我有一组数字。我需要计算给定范围内有多少个数字。 例如:对于给定的集合:{3,4,7,10,15,30}: numbers in range (0, 6) = 2 numbers in range (8, 40) = 3 numbers in range (0, 50) = 6 什么样的结构最适合这一目的?我所说的“最佳”是指执行上述操作最快的结构。此外,快速插入和删除也将受到欢迎…如果给您的数字集从未改变,一个简单的选择是将数字按升序排序,然后在范围的端点上使用,以确定包含在范围内的排序

假设我有一组数字。我需要计算给定范围内有多少个数字。 例如:对于给定的集合:
{3,4,7,10,15,30}

numbers in range (0, 6) = 2
numbers in range (8, 40) = 3
numbers in range (0, 50) = 6

什么样的结构最适合这一目的?我所说的“最佳”是指执行上述操作最快的结构。此外,快速插入和删除也将受到欢迎…

如果给您的数字集从未改变,一个简单的选择是将数字按升序排序,然后在范围的端点上使用,以确定包含在范围内的排序序列中的第一个元素所在的位置,以及不在范围内的第一个元素所在的位置。然后,您可以减去这两个位置的差来计算该范围内的元素数,或者只是在该范围内迭代以确定该范围内的所有数字。使用快速排序算法(如quicksort或heapsort),排序可以在O(n logn)时间内完成,每个查询只需O(logn)时间即可完成两个不同的二进制搜索

您可以通过多种方式潜在地加快这一速度。例如,如果您知道这些数字或多或少是均匀分布的,那么可以使用搜索代替二进制搜索来进行查找。这需要预期的时间O(logn)来完成每个查询,这比以前快了很多。如果您知道这些数字都在[0,N]范围内,那么在最坏的情况下,您可以使用更高级的数据结构(如a)将所有操作加速到O(logn)

如果另一方面,数字集可以增长和缩小,那么你可能需要考虑使用平衡二叉搜索树来存储你的数字。然后你可以对树(在时间O(log n)中)进行有效的搜索,以确定范围内的第一个数,而不在范围内的第一个数。


希望这有帮助!

这有什么问题

    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;
    }
静态整数计数(IList集、最小整数、最大整数)
{ 
整数计数=0;
foreach(集合中的int i)
如果(imin)
计数++;
返回计数;
}

这是计算几何中一个研究得很好的问题,它被称为。虽然你有一维版本。问题是,如果插入和删除很少,那么每个操作有多常见,在这种情况下,你可以将它们制成表格。这将给你O(n^2)存储和恒定时间查询。

如果数据集不会随时间变化,templatetypedef的答案是可以的,但您提到了快速插入和删除的需要。[编辑:David Eisenstat解释了如何通过两次O(log n)搜索来增加每个节点的计数,从而有效地对给定范围内的元素进行计数。]

在任何情况下,如果需要快速更新,解决问题的理想数据结构是或位树。此数据结构为以下两种操作提供O(logn)保证:

  • 查询:计算0和任意给定数字之间的元素数
  • 更新:在multiset中插入或删除某个给定数量的任意给定数量的副本
两个查询调用允许您使用
count(j)-count(i)
计算任意给定范围[i,j]中的元素数


Fenwick树上的查询和更新只涉及简单的按位操作和单个数组上的查找,因此使用此数据结构将在O(logn)上产生一个非常有竞争力的常数--我希望它比在更新下维护一个平衡的二叉树要快得多,这需要指针操作和树的重新平衡。

O(n)。二叉树会更快。将vEB树与红黑树进行比较,发现只有30%的改进。如果一个普通的旧trie不比这两个树都快,我会感到惊讶。所有这些结构的节点都需要增加一个
后代计数
字段。@davidisenstat-这很有趣!我认为这可能与事实上,对于24位,logn和logn都非常小。是的,你是对的,你确实需要扩充数据结构。谢谢你指出这一点!你能详细说明一下O(logn)是如何实现的吗平衡二叉树上的搜索可用于计算给定范围内的元素数?谢谢!每个节点x存储x左子代的后代数。此字段可在旋转后局部更新。搜索前,将累加器初始化为零。每当搜索使用节点y的右子代时,添加y的左descendant count加上累加器的1。当搜索停止时,累加器加上最后一个元素的左后代计数就是该元素的索引。感谢@davidesenstat。我可以看出插入或删除元素只需要更改O(log n)即可计算从根到元素的路径。我发现这个的4元和8元变体比二进制更快。YMMV。该死,你和templatetypedef的答案都很好,我不知道该接受哪一个…我想我会接受你的,因为我决定使用位树。