Given an array S of n integers, are there elements a, b, c, and d in S such that a + b + c + d = target? Find all unique quadruplets in the array which gives the sum of target.
Note:
- Elements in a quadruplet (a,b,c,d) must be in non-descending order. (ie, a ≤ b ≤ c ≤ d)
- The solution set must not contain duplicate quadruplets.
For example, given array S = {1 0 -1 0 -2 2}, and target = 0. A solution set is: (-1, 0, 0, 1) (-2, -1, 1, 2) (-2, 0, 0, 2)
求4个数的和为0的所有集合解~可以用和3Sum类似的解法来做,枚举第一二个数,然后用两个指针夹逼找到第三四个数,但这种解法复杂度为O(n^3)~还有一种O(n^2)复杂度的解法,先对num排序, 然后建一个dictionary, dict[num[i]+num[j]] = [(i,j) pairs 满足num[i] + num[j]], 而且这里的(i,j) pair总是满足i < j;然后用二层循环来搜, num[i]是四元组最小的数, num[j]是第二小的数, 判断dict中有没有target - (num[i] + num[j])这个key, 如果有, 就把找到的四个数加入最后的返回结果res~刚开始写的时候想在过程中直接处理重复元素,但老是不对,于是只能用set()去重~
class Solution:
# @return a list of lists of length 4, [[val1,val2,val3,val4]]
def fourSum(self, num, target):
if num is None or len(num) < 4: return []
num.sort()
res, dict = set(), {}
for i in xrange(len(num)):
for j in xrange(i + 1, len(num)):
if num[i] + num[j] not in dict:
dict[num[i] + num[j]] = [(i, j)]
else:
dict[num[i] + num[j]].append((i, j))
for i in xrange(len(num) - 3):
for j in xrange(i + 1, len(num) - 2):
remainder = target - (num[i] + num[j])
if remainder in dict:
for pair in dict[remainder]:
if pair[0] > j:
res.add((num[i], num[j], num[pair[0]], num[pair[1]]))
return [list(i) for i in res]
还有一种更简洁的写法,但思路是一样的~
class Solution:
# @return a list of lists of length 4, [[val1,val2,val3,val4]]
def fourSum(self, num, target):
if num is None or len(num) < 4: return []
num = sorted(num)
result = set()
cache = collections.defaultdict(set)
for i in range(len(num)):
for j in range(i + 1, len(num)):
for half in cache[target - num[i] - num[j]]:
result.add(tuple(list(half) + [num[i], num[j]]))
for j in range(i):
cache[num[i] + num[j]].add((num[j], num[i]))
return map(list, result)