3Sum
Given an array S of n integers, are there elements a, b, c 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
posted on 2016-06-29 16:10 Sheryl Wang 阅读(219) 评论(0) 编辑 收藏 举报