3Sum

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

Note: The solution set must not contain duplicate triplets.

For example, given array S = [-1, 0, 1, 2, -1, -4],

A solution set is:
[
  [-1, 0, 1],
  [-1, -1, 2]
]

这题是求出三个数字和为0的全部组合。做法很经典,是枚举第一个数字nums[i],后面就转换为求和为-nums[0]的two sum问题。由于要枚举的情况很多,所以对每个第一个数字的位置都采用hashmap不是很现实。先排序,再用two pointer的方法比较合适。这题的重点是如何去重。如果不在前端去掉重复,则在后端放入res的时候,需要对每个新加入的三数组合都需要进行判断,复杂度也很高,(这种后端去重的做法详见4sum这题)这种前期不去重的做法超时。

考虑前期去重,有两种方案。但是两种方案的共同点都是先对target去重。具体见代码:

第一种:类似permutation II的处理方法,对于一连串重复只取开始或者结束这个,但是是开始还是结束这个挑选需要留意:

对于target数字,如果我们把target数字放在最前面,则取连续重复数字中的第一个,这样对于有可能前两个数字一样的组合留出了可能。

同理如果把target放在最后,则应该取连续重复数字的最后一个,这样对于后两个数字一样的留下可能。

如果我们把target数字放前面,则再考虑避免l数字重复取,或者r数字重复取。在每次nums[l]+nums[r]==target时,我们同时向右移动l,向左移动r,但是如果移动后还和原数字一样,则会形成重复,所以要跳过。

 class Solution(object):
    def threeSum(self, nums):
        """
        :type nums: List[int]
        :rtype: List[List[int]]
        """
        if not nums or len(nums) < 3:
            return []
        nums.sort()   #先排序
        res = []
        for i in xrange(len(nums)-2):
            if i > 0 and nums[i] == nums[i-1]: #第一个位置的重复值处理
                continue
            target = 0 - nums[i]
            l = i + 1
            r = len(nums) - 1
            while l < r:
                if nums[l] + nums[r] < target:
                    l += 1
                elif nums[l] + nums[r] > target:
                    r -= 1
                else:
                    res.append([nums[i], nums[l], nums[r]])
                    l += 1
                    r -= 1 #也可以移动到while后面
                    while l < r and nums[l] == nums[l-1]: #第二个位置的重复值处理
                        l  += 1
# 实际是那个3个数字加起来为0,只需要对其中两个数字去重就可以 # while l < r and nums[r] == nums[r+1]: #第三个位置的重复值处理 # r -= 1
return res

复杂度为O(nlogn+n^2) = O(n^2).空间复杂度O(1).

另外一种去重方案是我们对target去重,但是不对l,r移动中做去重处理,只在添加结果时,在考虑l或者r元素是否重复。

比如是考察左元素,则检查l == i+1 or nums[l] != nums[l-1] 防止左元素和前面的结果产生重复。

新写法:

class Solution(object):
    def threeSum(self, nums):
        """
        :type nums: List[int]
        :rtype: List[List[int]]
        """
        if len(nums) < 3:
            return []
        nums.sort()
        res = []
        for i in xrange(len(nums)-2):
            if i == 0 or nums[i] != nums[i-1]: 
                target = 0 - nums[i]
                l = i+1
                r = len(nums)-1
                while l < r:     
                    if nums[l]+nums[r] < target:
                        l += 1
                    elif nums[l]+nums[r] > target:
                        r -= 1
                    else:
# 开头的数字,或者和前面的元素不重合
if l == i+1 or nums[l] != nums[l-1]: res.append([nums[i],nums[l],nums[r]]) l += 1 r -= 1 return res
原文地址:https://www.cnblogs.com/sherylwang/p/5627240.html