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 1:
public List<List<Integer>> fourSum(int[] num, int target) {
List<List<Integer>> result = new ArrayList<>();
int len = num.length;
if(len < 4) return result;
Arrays.sort(num);
for(int i=0; i<len-3; i++) {
if(i>0 && num[i]==num[i-1]) continue;
for(int j=i+1; j<len-2; j++) {
if(j>i+1 && num[j]==num[j-1]) continue;
int start = j+1;
int end = len-1;
while(start < end) {
int sum = num[i]+num[j]+num[start]+num[end];
if(sum == target) {
List<Integer> quadruplet = new ArrayList<>();
quadruplet.add(num[i]);
quadruplet.add(num[j]);
quadruplet.add(num[start]);
quadruplet.add(num[end]);
result.add(quadruplet);
do {
start++;
}while(start < end && num[start] == num[start-1]);
do {
end--;
}while(start < end && num[end] == num[end+1]);
} else if(sum < target) {
start++;
} else {
end--;
}
}
}
}
return result;
}
Solution 2:
public List<List<Integer>> fourSum(int[] num, int target) {
// Since we use set here, we don't need to dedup data
Set<List<Integer>> result = new HashSet<>();
Arrays.sort(num);
Map<Integer, Set<Pair>> map = new HashMap<>();
for (int i=0; i<num.length; i++) {
for (int j=0; j<i-1; j++) {
int a = num[j], b = num[i-1];
if (!map.containsKey(a+b)) {
map.put(a+b, new HashSet());
}
map.get(a+b).add(new Pair(a, b));
}
// Note the order of these two for-loops is critical
for (int j=i+1; j<num.length; j++) {
int pairSum = target - num[i] - num[j];
if (map.containsKey(pairSum)) {
for (Pair p : map.get(pairSum)) {
List l = new LinkedList();
l.add(p.first);
l.add(p.second);
l.add(num[i]);
l.add(num[j]);
result.add(l);
}
}
}
}
return new ArrayList<List<Integer>>(result);
}
class Pair {
int first;
int second;
public Pair(int first, int second) {
this.first = first;
this.second = second;
}
@Override
public int hashCode() {
return first*31 + second;
}
@Override
public boolean equals(Object d){
if (d == this) return true;
if (!(d instanceof Pair)) return false;
Pair p = (Pair) d;
return (this.first == p.first) && (this.second == p.second);
}
}
Reference: