这是2Sum问题的概括
给定未排序的数字数组,如何找到最接近任意目标的数字对。请注意,可能不存在完全匹配,因此O(n)
哈希表解决方案不适合此处。
我可以在O(n*log(n))
时间内为目标0解决问题:
按绝对值对数字进行排序。
遍历排序后的数组,保持相邻值之和的最小值。
这是有效的,因为三个对(+ / +,+ / - , - / - )都是由绝对值逻辑处理的。也就是说,当它们最接近0时,相同符号的对的总和被最小化,并且当该对的分量彼此最接近时,不同符号的对的总和被最小化。当按绝对值排序时,表示这两种情况。
如何将此概括为任意目标总和?
答案 0 :(得分:3)
在排序数组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 :(得分:2)
如果您要对数字进行排序,您的算法的复杂度至少为O(n*log(n))
。因此,您可以执行以下操作:对于每个数字v
,您可以执行二进制搜索,以在数组中查找数量最少的u
,其总和u + v
比目标更多。现在检查u + v
和u + t
,其中t
是排序数组中v
的前身。
这种复杂性是二分法搜索复杂度的n
倍,即O(n * log (n))
,因此您的整体复杂性仍为O(n*log(n))
。此解决方案也比您的建议更容易实现。
正如amit在对问题的评论中指出的那样,你可以做第二阶段的线性复杂性,提高速度。整体计算复杂性仍将保持不变,实施解决方案有点困难。