如何找到1T号码中最常见的号码?

时间:2013-04-22 06:55:26

标签: c algorithm sorting find

如何在1T(即10 ^ 12)个数字中找到最常用的数字(int类型)?

我的前提是:

  • 我的记忆仅限于4G(即4·10 ^ 9)字节。
  • 所有数字都存储在文件中作为输入。
  • 输出只是一个数字。
  • 所有数字(int类型)都存储在一个或serval文件中
  • 文件结构是二进制或行存储。

编辑于:2013.04.22 17:08 谢谢你的评论: 加:   - 外部存储不受限制。

4 个答案:

答案 0 :(得分:3)

首先请注意,问题至少与element distinctness problem一样难。

因此,解决方案应遵循相同的方法:

  1. 排序(使用external sort)并在计算每个数字的出现次数时进行迭代并寻找最大值。
  2. 散列解决方案:将数字散列到适合内存的存储桶中(请注意,所有相同数量的出现都会被散列到同一个存储桶中),对于每个存储桶 - 找到最常用的数字并存储它。然后通过所有桶的所有候选人,并选择最好的。
    在这里,你可以对每个桶进行排序(在内存中)并找到最常用的数字,或者你可以创建一个histogram(使用哈希映射,具有不同的哈希函数)来查找频率桶中的每个项目。
    请注意,存储桶写在磁盘上,一个接一个地装入存储器,每次只有一小部分数据存储在RAM上。
  3. 另一种更具可扩展性的方法可能是使用map-reduce,使用简单的map-reduce步骤来计算每个数字的出现次数,然后找到最大值:

    map(number):
      emit(number,'1')
    reduce(number,list):
      emit (number, size(list))
    

    剩下的就是找到具有最高值的数字 - 这可以在线性扫描中完成。

答案 1 :(得分:1)

使用文件系统存储数字计数器是什么意思?

例如,如果您的数字是uint32,则可以创建65536个目录,每个目录中包含65536个文件。 目录名称将是一个数字的两个高字节,文件名 - 低两个字节。当你遇到数字X,你将它分成两部分并获取文件名,打开该文件并在其中增加计数器(或写入1,如果文件不存在)。

填写该文件结构后,您可以递归扫描具有最大值的树查找文件。

这将非常缓慢,但几乎不会吃任何RAM。

答案 2 :(得分:0)

使用哈希表,键是数字,值是计数。 O(n)将所有数字插入哈希表O(唯一数字)以找到最常见的数字。

答案 3 :(得分:0)

蛮力:

  • remember = 0;
  • 重复:
    • 取第一个未标记的数字并计算其在文件中的出现次数(n1)。
    • 将每个出现的数字标记为已读。 (用空格f.e覆盖它)
    • if(n1> remember)remember = n1;