Question
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)
Solution
我们可以follow 3Sum的思路完成4Sum。
这里给出average time小于O(n3)的方法。
我们可以把4Sum拆解为2Sum的问题。首先,构造map,key为pair sum,value为list of pairs。然后,照着2Sum的方法,得出结果。
1 public class Solution { 2 public List<List<Integer>> fourSum(int[] nums, int target) { 3 Arrays.sort(nums); 4 Map<Integer, List<List<Integer>>> map = new HashMap<Integer, List<List<Integer>>>(); 5 Set<List<Integer>> result = new HashSet<List<Integer>>(); 6 for (int i = 0; i < nums.length; i++) { 7 for (int j = i + 1; j < nums.length; j++) { 8 int sum = nums[i] + nums[j]; 9 if (map.containsKey(target - sum)) { 10 List<List<Integer>> pairs = map.get(target - sum); 11 for (List<Integer> pair : pairs) { 12 // m1 < m2 13 int m1 = pair.get(0); 14 int m2 = pair.get(1); 15 // m3 < m4 16 int m3 = i; 17 int m4 = j; 18 if (m1 == m3 || m1 == m4 || m2 == m3 || m2 == m4) { 19 continue; 20 } else { 21 if (m2 < m3) { 22 result.add(Arrays.asList(nums[m1], nums[m2], nums[m3], nums[m4])); 23 } else if (m2 > m4) { 24 result.add(Arrays.asList(nums[m1], nums[m3], nums[m4], nums[m2])); 25 } else { 26 result.add(Arrays.asList(nums[m1], nums[m3], nums[m2], nums[m4])); 27 } 28 } 29 } 30 } 31 // Add current pair into map 32 List<Integer> list = new ArrayList<Integer>(); 33 list.add(i); 34 list.add(j); 35 if (map.containsKey(sum)) { 36 map.get(sum).add(list); 37 } else { 38 List<List<Integer>> tmp2 = new ArrayList<Lis<Integer>>(); 39 tmp2.add(list); 40 map.put(sum, tmp2); 41 } 42 43 } 44 } 45 return new ArrayList<List<Integer>>(result); 46 } 47 }