从每个数组中提取一个数字,使数字之和为0?

时间:2013-09-30 12:51:31

标签: arrays algorithm

我正在为我的校园实习做准备。我遇到了一个问题,就是这样:

给出3个数组,比如

array 1: {2,1,4,7}
array 2: {3,-3,-8,0}
array 3: {-1,-4,-7,6}

我们必须从每个数组中提取一个数字并形成三元组,使得三元组中的数字之和为0,或者为该事实的任何数字。

例如,对于上述情况,其中一个解决方案可以是{2, -8, 6}

目前,我还没有想到除了蛮力方法之外的任何解决方案,这将花费O(n^3)时间。如何在较短的时间内完成这项工作?

提前致谢。

4 个答案:

答案 0 :(得分:7)

一个非常简单的解决方案如下:

给定目标T

  • 排序第三个数组
  • 对于第一个数组中的每个数字N1
    • 对于第二个数组中的每个数字N2
      • 二进制搜索第三个数组(T-N1-N2)

运行时间= O(n^2 log n)

对于第三个数组,你也可以使用一个哈希表,给你一个预期复杂度O(1)每次查找,总共O(n^2),但我总觉得这有点作弊,如同你依赖于好的分布。

答案 1 :(得分:6)

问题与3SUM problem密切相关。事实上,3SUM问题可以简化为你所说的问题(三个数组填充相同的n个元素),所以问题是 3SUM-hard

比O(n ^ 2)解更快的解决方案因此非常不可能,因为这会与3SUM问题的推测二次时间下限相矛盾。

答案 2 :(得分:2)

你可以在O(n ^ 2):

中完成
  • 将第二个数组按升序排序
  • 将第三个数组按降序排序
  • 遍历第一个数组。
  • 第二个或第三个数组的增量索引取决于总和是否为负数 正。

    // Asssume array2 and array3 are sorted as mentioned above
    // array2: {-8,-3,0,3}
    // array3: {6,-1,-4,-7}
    foreach (e1 in array1)
    {
        int i2 = 0;
        int i3 = 0;
        while (i2 < array2.Length && i3 < array3.Length)
        {
            int sum = e1 + array2[i2] + array3[i3];
            if (sum == 0) Console.WriteLine( e1, array2[i2], array3[i3]);
            if (sum < 0) ++i2 else ++i3;
        }
    

    }

相关:Finding three elements in an array whose sum is closest to a given number

答案 3 :(得分:1)

如果对一个数组进行排序并对其他两个数组中任何一对元素之和的否定执行二进制搜索,则可以将复杂度降低到O(log(N) * N^2)

如果数组中数字值的范围相对较小,则可以通过使用计数排序算法或其他一些线性非比较排序算法来进一步改善这一点。

另一个改进是使用哈希集来表示第一个数组的数量,从而得到凯文提出的O(N ^ 2)的复杂性。