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)
We can follow the idea of 3sum, and so on, the complexity of ksum is O (n ^ (k-1). In 3sum, another layer of loop is set, which is equal to n times to calculate 3sum.
1 public class Solution { 2 public ArrayList<ArrayList<Integer>> fourSum(int[] num, int target) { 3 ArrayList<ArrayList<Integer>> res = new ArrayList<ArrayList<Integer>>(); 4 if (num==null || num.length==0) return res; 5 Arrays.sort(num); 6 for (int i=num.length-1; i>=3; i--) { 7 if (i<num.length-1 && num[i]==num[i+1]) continue; 8 ArrayList<ArrayList<Integer>> sets = threeSum(0, i-1, num, target-num[i]); 9 for (int ii=0; ii<sets.size(); ii++) {10 ArrayList<Integer> temp = sets.get(ii);11 temp.add(num[i]);12 }13 res.addAll(sets);14 }15 return res;16 }17 18 public ArrayList<ArrayList<Integer>> threeSum(int start, int end, int[] num, int target) {19 ArrayList<ArrayList<Integer>> res = new ArrayList<ArrayList<Integer>>();20 for (int j=end; j>=2; j--) {21 if (j<end && num[j]==num[j+1]) continue;22 ArrayList<ArrayList<Integer>> sets = twoSum(0, j-1, num, target-num[j]);23 for (int jj=0; jj<sets.size(); jj++) {24 ArrayList<Integer> temp = sets.get(jj);25 temp.add(num[j]);26 }27 res.addAll(sets);28 }29 return res;30 }31 32 public ArrayList<ArrayList<Integer>> twoSum(int l, int r, int[] num, int target) {33 ArrayList<ArrayList<Integer>> res = new ArrayList<ArrayList<Integer>>();34 while (l < r) {35 if (num[l]+num[r] == target) {36 ArrayList<Integer> set = new ArrayList<Integer>();37 set.add(num[l]);38 set.add(num[r]);39 res.add(new ArrayList<Integer>(set));40 l++;41 r--;42 while (l<r && num[l] == num[l-1]) {43 l++;44 }45 while (l<r && num[r] == num[r+1]) {46 r--;47 }48 }49 else if (num[l]+num[r] < target) {50 l++;51 }52 else {53 r--;54 }55 }56 return res;57 }58 }
(Not to be further explored) There is also a way on the Internet, that is, if we want to make the time more complex, we can actually consider using the binary method. If we want to find out all the pair pairs, then perform a two sum match again, we know that two sum is a Sort plus a linear operation, and the number of all pair is O (n-1) + (n-2) +... + 1) = O (N (n-1)/2) = O (N ^ 2 ). Therefore, if a special linear sorting algorithm is not used for sorting O (N ^ 2 * log (N ^ 2) = O (N ^ 2*2 logn) = O (N ^ 2 * logn), the algorithm complexity is higher than the O (N ^ 3) of the previous method.
Although the idea is clear, the details will be handled in many cases. First, we need to create a data structure for each pair to store the value of the element and the corresponding index, this is done later to check whether there are overlapping indexes when two pairs of pair are matched to obtain the target value. If so, it indicates that they are not a legal result, because it is not four different elements. Next we have to sort these pair, so we need to define the comparable function for pair. Finally, when two sum is matched, because pair is no longer a value, you cannot directly skip the same one as in two sum. Each group must be viewed, in this case, there will be duplicates, so we have to define the hashcode and equality function for each tuple consisting of four elements, so that we can put the current result in a hashset, in this way, if the new result is duplicated, The result set is not added.
1 private ArrayList<ArrayList<Integer>> twoSum(ArrayList<Pair> pairs, int target){ 2 HashSet<Tuple> hashSet = new HashSet<Tuple>(); 3 int l = 0; 4 int r = pairs.size()-1; 5 ArrayList<ArrayList<Integer>> res = new ArrayList<ArrayList<Integer>>(); 6 while(l<r){ 7 if(pairs.get(l).getSum()+pairs.get(r).getSum()==target) 8 { 9 int lEnd = l;10 int rEnd = r;11 while(lEnd<rEnd && pairs.get(lEnd).getSum()==pairs.get(lEnd+1).getSum())12 {13 lEnd++;14 }15 while(lEnd<rEnd && pairs.get(rEnd).getSum()==pairs.get(rEnd-1).getSum())16 {17 rEnd--;18 }19 for(int i=l;i<=lEnd;i++)20 {21 for(int j=r;j>=rEnd;j--)22 {23 if(check(pairs.get(i),pairs.get(j)))24 {25 ArrayList<Integer> item = new ArrayList<Integer>();26 item.add(pairs.get(i).nodes[0].value);27 item.add(pairs.get(i).nodes[1].value);28 item.add(pairs.get(j).nodes[0].value);29 item.add(pairs.get(j).nodes[1].value);30 //Collections.sort(item);31 Tuple tuple = new Tuple(item);32 if(!hashSet.contains(tuple))33 {34 hashSet.add(tuple);35 res.add(tuple.num);36 }37 } 38 }39 }40 l = lEnd+1;41 r = rEnd-1;42 }43 else if(pairs.get(l).getSum()+pairs.get(r).getSum()>target)44 {45 r--;46 }47 else{48 l++;49 }50 }51 return res;52 }53 private boolean check(Pair p1, Pair p2)54 {55 if(p1.nodes[0].index == p2.nodes[0].index || p1.nodes[0].index == p2.nodes[1].index)56 return false;57 if(p1.nodes[1].index == p2.nodes[0].index || p1.nodes[1].index == p2.nodes[1].index)58 return false;59 return true;60 }
Leetcode: 4Sum