比较数组中的100万个整数而不先对其进行排序

时间:2017-08-15 11:00:09

标签: c# algorithm

我有一项任务是找出随机数组中每个整数之间的差异并返回最低差值。要求是整数可以在0和int.maxvalue之间,并且数组将包含100万个整数。

我把一些代码放在一起,对于少量整数工作正常,但是花费很长时间(我大部分时间都放弃等待)要做一百万。我的代码如下,但我正在寻找有关如何提高性能的一些见解。

for(int i = 0; i < _RandomIntegerArray.Count(); i++) {
  for(int ii = i + 1; ii < _RandomIntegerArray.Count(); ii++) {
    if (_RandomIntegerArray[i] == _RandomIntegerArray[ii]) continue;

    int currentDiff = Math.Abs(_RandomIntegerArray[i] - _RandomIntegerArray[ii]);

    if (currentDiff < lowestDiff) {
      Pairs.Clear();
    }

    if (currentDiff <= lowestDiff) {
      Pairs.Add(new NumberPair(_RandomIntegerArray[i], _RandomIntegerArray[ii]));
      lowestDiff = currentDiff;
    }
  }
}

向所有指出我不排序的人道歉;不幸的是,不允许排序。

6 个答案:

答案 0 :(得分:14)

想象一下,您已经从随机数组中找到了一对整数python script.py aaaaaa.txt a,因此ba > b是所有可能的整数对中最低的在阵列中。

数组中是否存在a-b整数c,即a > c > b介于ca之间?显然,答案是&#34; no&#34; ,因为否则您选择b{a, c}对。

这可以解决您的问题:{c, b}a必须在排序数组中彼此相邻。排序可以在O(N * log N)中完成,搜索可以在O(N)中完成 - 这是对O(N 2 )算法的改进。

答案 1 :(得分:2)

根据@JonSkeet尝试先排序数组,然后只比较连续的数组项,这意味着你只需要迭代一次数组:

    Array.Sort(_RandomIntegerArray);
    for (int i = 1; i < _RandomIntegerArray.Count(); i++)
    {
        int currentDiff = _RandomIntegerArray[i] - _RandomIntegerArray[i-1];
        if (currentDiff < lowestDiff)
        {
            Pairs.Clear();
        }

        if (currentDiff <= lowestDiff)
        {
            Pairs.Add(new NumberPair(_RandomIntegerArray[i], _RandomIntegerArray[i-1]));
            lowestDiff = currentDiff;
        }

    }

在我的测试中,这导致&lt; 100万件物品耗时200毫秒。

答案 2 :(得分:1)

你可能有2.15或43亿(签名或未签名)的一百万个整数。这意味着最大可能的最小距离约为2150或4300.假设最大可能最小距离为D.

将合法整数划分为长度为D的组。创建一个以整数数组作为值的整数键入的散列h。通过获取每个元素x并将其添加到h [x / D]来处理数组。

这样做的一点是,任何有效的点对都包含在某些k的h(k)中,或者总体上包含在h(k)和h(k + 1)中。

通过遍历哈希的键并检查与相邻键相关联的点来找到您的点对。您可以根据需要进行排序,或使用位向量或任何其他方法,但现在您正在处理小数组(平均每个数组1个元素)。

答案 3 :(得分:0)

由于数组的元素是b / w 0到int.maxvalue,所以我认为maxvalue将小于1百万。如果是这样你只需要将数组[maxvalue]初始化为0,然后当你读取100万个值时,会增加数组中的值。

现在读取此数组并找到其他人描述的最低值,就像所有值都已排序一样。如果在任何元素存在超过1的值,则其值将> 1,因此您可以轻松地说min。差异是0。

注意 - 此方法仅在不使用排序时才有效,更重要的是int.maxvalue&lt;&lt;&lt;&lt;&lt;(小于)10 ^ 6(1百万)。

答案 4 :(得分:0)

如果您不指望每次迭代,都会有所帮助

int countIntegers = _RandomIntegerArray.Count();
for(int i = 0; i < countIntegers; i++) {
    //...
    for(int ii = i + 1; ii < countIntegers; ii++) {
        //...

鉴于Count()仅在每次成功计数时返回数组中的Ints数量,并且直到修改后才修改数组或缓存输出。

答案 5 :(得分:-1)

  

如何将数组拆分为arraysize/number of processors大小的块并在不同的线程中运行每个块。 (Neil

假设三个部分 A,B C 的尺寸尽可能接近。
对于每个零件,找到最小的“零件内”差异,以及与当前零件中的第一个零件和下一个零件中的第二个零件(A是C中的下一个零件)的对的差异。
使用O(n²)时间的方法,n / 3应该取九分之一,完成2 * 3次,这相当于三分之二加上组合结果的变化。
这个调用是递归地应用 - 记住Карацуба/ Karatsuba乘法?
等等 - 毕竟可能使用两个部分,三分之四的努力 - 非常接近“Karatsuba”。 (当没有看到如何使用偶数个部件时,我正在考虑多处理,每个处理器都做“相同”。)