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)
题目大意:跟3Sum类似,这个题是在一个数组中找出4个数的和等于target,如果还用3Sum这种做法,那么复杂度会到O(N^3),效率有点不能忍。
第一种:我想到的第一种方法是枚举a+b的和,放入一个数组,然后对这个数组排序,然后以Binary Search查找target-c-d是否存在于这个数组中,这里有个问题就是排序数组还要记录a、b的下标,只能定义class或者搞个二维数组,时间复杂服是O(N^2*logN)。
To add...
第二种:后来又想到一种方法就是把枚举的a+b的和放入HashMap,以a+b之和作为key,以这两个数的下标作为value,如果分散平均的话这样的时间复杂度是O(N^2),最坏情况是所有的数都一样,那么n^2个数的和只有一个key,List里有n^2个和,退化到O(N^4)。
public List<List<Integer>> fourSum(int[] num, int target) { List<List<Integer>> res = new ArrayList<>(); if (num == null || num.length < 4) { return res; } int len = num.length; Map<Integer, List<Integer>> map = new HashMap<>(); Set<String> unique = new HashSet<>(); for (int i = 0; i < len; i++) { for (int j = i + 1; j < len; j++) { int key = num[i] + num[j]; if (map.get(key) == null) { List<Integer> list = new ArrayList<>(); list.add(i * len + j); map.put(key, list); } else { List<Integer> list = map.get(key); list.add(i * len + j); map.put(key, list); } } } for (int i = 0; i < len; i++) { for (int j = i + 1; j < len; j++) { int key = target - num[i] - num[j]; List<Integer> list = map.get(key); if (list == null || list.isEmpty()) { continue; } for (Integer pos : list) { int x = pos / len; int y = pos % len; if (i == x || i == y || j == x || j == y || x == y) continue; int[] t = new int[]{num[i], num[j], num[x], num[y]}; Arrays.sort(t); String uni = String.valueOf(t[0]) + t[1] + t[2] + t[3]; if (!unique.contains(uni)) { unique.add(uni); res.add(Arrays.asList(t[0], t[1], t[2], t[3])); } } } } return res; }