在未排序的数组中找到一对数字,其总和最接近任意目标

时间:2014-04-28 16:22:36

标签: algorithm

这是2Sum问题的概括

给定未排序的数字数组,如何找到最接近任意目标的数字对。请注意,可能不存在完全匹配,因此O(n)哈希表解决方案不适合此处。

我可以在O(n*log(n))时间内为目标0解决问题:

  1. 按绝对值对数字进行排序。

  2. 遍历排序后的数组,保持相邻值之和的最小值。

  3. 这是有效的,因为三个对(+ / +,+ / - , - / - )都是由绝对值逻辑处理的。也就是说,当它们最接近0时,相同符号的对的总和被最小化,并且当该对的分量彼此最接近时,不同符号的对的总和被最小化。当按绝对值排序时,表示这两种情况。

    如何将此概括为任意目标总和?

2 个答案:

答案 0 :(得分:3)

步骤1:以非递减顺序对数组进行排序。复杂性:O(n lg n)

第2步:从两端向内扫描。复杂性:O(n)

在排序数组A上,让l指向最左边(即最小)元素,r指向最右边(即最大)元素。

 while true:
   curSum = A[ l ] + A[ r ]
   diff = currSum - target
   if( diff > 0 ):
      r = r - 1
   else:
      l = l + 1

如果曾经diff == 0,那么你就得到了2Sum的完美匹配。

否则,寻找diff 中的符号变化,即从正变为负,或从负变为正。无论何时发生转换,无论是在更改之前还是之后,currSum都最接近target

总体复杂度:由于步骤1,O(n log n)。

答案 1 :(得分:2)

如果您要对数字进行排序,您的算法的复杂度至少为O(n*log(n))。因此,您可以执行以下操作:对于每个数字v,您可以执行二进制搜索,以在数组中查找数量最少的u,其总和u + v比目标更多。现在检查u + vu + t,其中t是排序数组中v的前身。

这种复杂性是二分法搜索复杂度的n倍,即O(n * log (n)),因此您的整体复杂性仍为O(n*log(n))。此解决方案也比您的建议更容易实现。

正如amit在对问题的评论中指出的那样,你可以做第二阶段的线性复杂性,提高速度。整体计算复杂性仍将保持不变,实施解决方案有点困难。