我需要使用大尺寸的阵列

时间:2010-07-08 16:30:05

标签: c#

我的要求是在长度为10 ^ 15的整数数组中找到重复的数字。 我需要在一次通过中找到一份副本。我知道从数组中找到重复数字的方法(逻辑),但我怎样才能处理如此大的数字。

8 个答案:

答案 0 :(得分:7)

一个10 ^ 15整数的数组需要超过1 PB的存储空间。你说它可以一次完成,所以不需要存储所有数据。但即使阅读这些数据也需要很多的时间。

但等等,如果数字是整数,它们会落入一定的范围,比方说N = 2 ^ 32。因此,您只需要搜索最多N + 1个数字即可找到重复数据。现在这是可行的。

答案 1 :(得分:4)

您可以使用长度为= 2 ^(32-5)= 0x0800000

的BitVector数组

每个有效的int32号都有一点。

注意:简易解决方案(BitArray)不支持适当的构造函数。

BitVector32[] bv = new BitVector32[0x8000000];
int[] ARR = ....;   // Your array
foreach (int I in ARR)
{
    int Element = I >> 5;
    int Bit = I & 0x1f;
    if (bv[Element ][Bit])
    {
        // Option for First Duplicate Found
    }
    else
    {
        bv[I][Bit] = true;
    }
}

答案 2 :(得分:1)

您需要不同的数据结构。我怀疑要求不是真的使用数组 - 我希望不会,因为数组只能容纳Int32.MaxValue个元素,即2,147,483,647 ...远小于10 ^ 15。即使在64位机器上,我相信CLR要求阵列最多包含那么多元素。 (例如,请参阅Array.CreateInstance的文档 - 即使您可以将边界指定为64位整数,如果它们实际上很大,它也会抛出异常。)

现在,如果您可以解释真实要求是什么,我们很可能会建议其他数据结构。

如果这是一个理论问题而不是一个实际问题,那么如果你能告诉我们这些限制也会有所帮助。

例如,如果你有足够的内存用于数组本身,那么要求2 ^ 24个字节来存储你已经看过的数字(每个值一位)并不需要太多。当然,这假设值本身是32位整数。从空数组开始,并为找到的每个数字设置相关位。如果您发现即将设置已设置的那个,那么您已找到第一个副本。

答案 3 :(得分:0)

您可以按正常方式声明:new int[1000000000000000]。但是这只适用于64位机器;你可以期望在32位机器上存储的最大值是2GB以上。

实际上,您将无法将整个阵列存储在内存中。你需要想出一种在较小的块中生成它的方法,并单独检查这些块。

阵列中的数据是什么?也许你不需要一次性生成它。或者也许你可以将数据存储在一个文件中。

答案 4 :(得分:0)

您不能声明大小大于Int32.MaxValue(2 ^ 31,或大约2 * 10 ^ 9)的数组,因此您必须将数组链接在一起或使用List<int>来保存所有数组价值观。

答案 5 :(得分:0)

无论数组大小如何,您的算法都应该是相同的。你得到的最佳时间复杂度当然是(理想情况下)O(n)

考虑以下算法的伪代码:

  1. 创建一个等于数组中数字范围的HashSet<int>容量。
  2. 遍历数组中的每个数字,并检查它是否已存在于hashset中。
    • 如果不是,请立即将其添加到哈希集。
    • 如果是,您发现了重复。
  3. 这里的内存使用远非微不足道,但如果你想要速度,它就能完成这项工作。

答案 6 :(得分:0)

问题,

1)是数组10 ^ 15

中的项目数

2)或者物品的价值可以是10 ^ 15?

如果是#1:

你从哪里拉数钱?如果它是一个文件,你可以单步执行它。

是否有超过2,147,483,647个唯一数字?

如果是#2:

int64可以处理数字

如果#1和#2:

是否有超过2,147,483,647个唯一数字?

如果少于2,147,483,647个唯一数字,您可以使用List&lt; bigint&gt;

答案 7 :(得分:0)

你不需要做任何事情。根据定义,将存在重复,因为2 ^ 32&lt; 10 ^ 15 - 没有足够的数字来唯一地填充10 ^ 15阵列。 :)

现在,如果还有一个额外的要求,你知道哪里重复是......那是另一个故事,但它不是原来的问题。