57.3Sum

1.Description(Medium)

Given an array S_of n integers, are there elements a,b, c in S such thata + b + c = 0. Find all unique triplets in the array which gives the sum of zero.

Notice

Elements in a triplet (a,b,c) must be in non-descending order. (ie, a ≤ b ≤ c)

The solution set must not contain duplicate triplets.

Example

For example, given array S ={-1 0 1 2 -1 -4}, A solution set is:

(-1, 0, 1)
(-1, -1, 2)

2.Code

Version 1:

经典题目,先排序array,利用a+b=-c,遍历array,使每次的integer = -c,从两头寻找a和b使得a+b=-c。主要难点在于duplicate solution的处理。(因为array里面的值有重复的)此解法复杂度为O(n^2)。

这道题让我们求三数之和,比之前那道要复杂一些,我们还是要首先对原数组进行排序,然后开始遍历排序后的数组,这里注意不是遍历到最后一个停止,而是到倒数第三个就可以了,然后我们还要加上重复就跳过的处理,对于遍历到的数,我们用0减去这个数得到一个sum,我们只需要再之后找到两个数之和等于sum即可,这样一来问题又转化为了求two sum,这时候我们一次扫描,找到了等于sum的两数后,加上当前遍历到的数字,按顺序存入结果中即可,然后还要注意跳过重复数字。题目要求的是a+b+c=0,问题可以推广到a+b+c=target。3sum问题可以转化为2sum问题:对于任意一个A[i],在数组中的其他数中解2sum问题,目标为target-A[i]。与2sum那题不同,这题要求返回的不是index而是数字本身,并且解不唯一。同时要求解排序并去重。

对排序来说,2sum中的双指针法更为方便,因为算法本身就用到排序。双指针排序法本身会去除一些重复的可能性:

(1, 2, 3, 4), target = 6

在扫描1时,解(2, 3, 4)的2sum = 5问题,找到一个解(1, 2, 3)。

在扫描2时,应当只对后面的数解2sum问题,即对(3, 4)解2sum = 4问题。这样避免再次重复找到解(1, 2, 3)。

但当存在重复数字时,光靠排序仍然无法去重:

(1, 2, 2, 2, 3, 4), target = 9

扫描第一个2时,解(2, 2, 3, 4)中的2sum=7问题,得到解(2, 3, 4)

扫描第二个2时,解(2, 3, 4)中的2sum=7问题,仍然会得到(2, 3, 4)

去除因重复数字而造成重复解有两个办法,

一是将结果存到一个hashset。

而另一种方法就是在扫描数组时跳过重复的数字。上例中,只扫描1, 2, 3, 4来求相应的2sum问题。进一步简化,可以只扫描1, 2。因为3已经是倒数第二个数字,不可能有以它为最小数字的解。

这里注意两次avoid duplicate solution,一次是在选择target的时候,一次是在内循环里面在剩余的array中寻求 2 sum 的解的时候

Version 2: 套用 NSum 模板

Last updated

Was this helpful?