计算十亿个元素列表中的唯一元素的最快方法是什么?

And*_*ehi 30 c# memory algorithm collections

我的问题不常见.让我们想象几十亿字符串.字符串通常少于15个字符.在此列表中,我需要找出唯一元素的数量.

首先,我应该使用什么对象?你不应该忘记,如果我添加一个新的元素,我必须检查它是否已经存在于列表中.这在一开始并不是问题,但在几百万字后,它确实会减慢这个过程.

这就是为什么我认为Hashtable是这项任务的理想选择,因为检查列表理想情况下只有log(1).不幸的是.net中的单个对象只能是2GB.

下一步将实现一个包含2GB哈希表列表的自定义哈希表.

我想知道也许你们中的一些人知道更好的解决方案.(电脑规格极高.)

D.S*_*ley 29

我会跳过数据结构练习并只使用SQL数据库.为什么要编写另一个必须分析和调试的自定义数据结构,只需使用数据库.他们非常擅长回答这样的问题.

  • 这实际上取决于他的应用程序约束,并做出一个可能无效的假设. (5认同)
  • (1)数据库针对基于集合的函数进行了优化 - 存在,交集,计数等.(2)C#在我上次检查时有数据库访问权限(3)如果数据集大于可用/有效内存大小,则自定义数据结构变得非常困难 - 考虑一下如何将trie的部分分页到磁盘并使其高效(4)如果你需要更多的话,不要排除加载数据的成本一旦(5)尝试编写一个多线程可以遍历并允许修改的特里 (4认同)
  • 像SQL Server这样的数据库引擎针对大量数据进行了优化.任何内存中的算法都存在花费太多时间并导致过多分页和/或线程争用的风险.在这种情况下,我认为你不应该排除数据库可能是最快的. (3认同)
  • 这是一个编程问题,而不是查询问题.(是的,查询是程序,但让我们避开它.)加上OP将问题标记为C#. (2认同)
  • 这是一个非常糟糕的想法,与使用trie跟踪你看到的字符串的数据进行单次迭代相比,这将是一个永恒的想法.我唯一遗憾的是,我只能投票一次. (2认同)
  • +1最实用的答案.我发誓没有人理解"快"这个词.如果您花费6个小时创建/测试自己的自定义哈希表,则比糖蜜慢.写一些东西来填充数据库然后写一些东西来查询它需要大约十分钟(加上传输时间).电脑时间很便宜.程序员时间**贵**.想一想. (2认同)
  • @Josh:大多数程序员不喜欢听到答案_well不写程序解决问题,使用存在的东西_ (2认同)

Lee*_*Lee 23

我会考虑TrieDirected非循环字图,它应该比哈希表更节省空间.对字符串成员资格的测试将是O(len),其中len是输入字符串的长度,这可能与字符串散列函数相同.

  • 我们不要混淆我们的Ns.对DAWG中的成员资格的测试将是O(n),但是n是字符串中的字符数,而不是集合中的字符串数.巨大的差异. (3认同)

Kir*_*now 7

This can be solved in worst-case O(n) time using radix sort with counting sort as a stable sort for each character position. This is theoretically better than using a hash table (O(n) expected but not guaranteed) or mergesort (O(n log n)). Using a trie would also result in a worst-case O(n)-time solution (constant-time lookup over n keys, since all strings have a bounded length that's a small constant), so this is comparable. I'm not sure how they compare in practice. Radix sort is also fairly easy to implement and there are plenty of existing implementations.

If all strings are d characters or shorter, and the number of distinct characters is k, then radix sort takes O(d (n + k)) time to sort n keys. After sorting, you can traverse the sorted list in O(n) time and increment a counter every time you get to a new string. This would be the number of distinct strings. Since d is ~15 and k is relatively small compared to n (a billion), the running time is not too bad.

This uses O(dn) space though (to hold each string), so it's less space-efficient than tries.