Given an array nums
of n integers and an integer target
, are there elements a, b, c, and d in nums
such that a + b + c+ d = target
? Find all unique quadruplets in the array which gives the sum of target
.
Note:
The solution set must not contain duplicate quadruplets.
Example:
Given array nums = [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] ]
法I:在3Sum的基础上,多加一个循环。时间复杂度O(n3)。
法II:使用HashTable。O(N^2)把所有pair存入hash表,pair中两个元素的和就是hash值。那么接下来求4sum就变成了在所有的pair value中求 2sum,这个就成了线性算法了。所以整体上这个算法是O(N^2)+O(n) = O(N^2)。
class Solution { public List<List<Integer>> fourSum(int[] nums, int target) { List<List<Integer>> ret = new ArrayList<>(); Map<Integer, List<List<Integer>>> twoSum = new HashMap<>(); Map<Integer, Integer> cnt = new HashMap<>(); //count of each num //sort array Arrays.sort(nums); for(int i = 0; i < nums.length; i++){ //update count if(cnt.get(nums[i])==null) cnt.put(nums[i],1); else cnt.put(nums[i],cnt.get(nums[i])+1); //initialize map if(i>0 && nums[i]==nums[i-1]) continue;//avoid repeat for(int j = i+1; j < nums.length; j++){ if(j > i+1 && nums[j]==nums[j-1]) continue; //avoid repeat List<Integer> list = new ArrayList<>(); list.add(nums[i]); list.add(nums[j]); List<List<Integer>> listGroup = twoSum.get(nums[i]+nums[j]); if(listGroup ==null ){ listGroup = new ArrayList<>(); } listGroup.add(list); twoSum.put(nums[i]+nums[j], listGroup); } } //iterate map to find target sum Set<Integer> keys = twoSum.keySet(); for (int key : keys) { List<List<Integer>> listGroupA = twoSum.get(key); for(List<Integer> listA: listGroupA){ List<List<Integer>> listGroupB = twoSum.get(target - key); if(listGroupB == null) continue; for(List<Integer> listB: listGroupB){ //check whether count of num is enough int a = listA.get(0); int b = listA.get(1); int c = listB.get(0); int d = listB.get(1); if(Math.max(a,b) > Math.min(c,d)) continue; //四个数两两组合,有6种情况,这里只取两个最小的数在listA的情况,去重 //check count of num cnt.put(a,cnt.get(a)-1); cnt.put(b,cnt.get(b)-1); cnt.put(c,cnt.get(c)-1); cnt.put(d,cnt.get(d)-1); if(cnt.get(a) >= 0 && cnt.get(b) >= 0 && cnt.get(c) >= 0 && cnt.get(d) >= 0){ //find one list List<Integer> listC = new ArrayList<>(); listC.addAll(listA); listC.addAll(listB); ret.add(listC); } //recover count of num cnt.put(a,cnt.get(a)+1); cnt.put(b,cnt.get(b)+1); cnt.put(c,cnt.get(c)+1); cnt.put(d,cnt.get(d)+1); } } } return ret; } }