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: 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] ]
public class Solution {
public List<List<Integer>> fourSum(int[] nums, int target) {
List<List<Integer>> res = new LinkedList<List<Integer>>();
Arrays.sort(nums);
if (nums.length < 4) {
return res;
}
int max = nums[nums.length - 1];
if (nums[0] * 4 > target || 4 * max < target) {
return res;
}
for (int i = 0; i < nums.length - 3; i++) {
int first = nums[i];
if (i > 0 && first == nums[i - 1]) {
continue;
}
if (first + 3 * max < target) {
continue;
}
if (4 * first > target) {
break;
}
if (4 * first == target) {
if (nums[i + 3] == first) {
res.add(Arrays.asList(first, first, first, first));
}
break;
}
threeSum(nums, target - first, i + 1, res, first);
}
return res;
}
private void threeSum(int[] nums, int target, int start, List<List<Integer>> res, int first) {
if (start > nums.length - 3) {
return;
}
int max = nums[nums.length - 1];
if (3 * nums[start] > target || 3 * max < target) {
return;
}
for (int i = start; i < nums.length - 2; i++) {
int second = nums[i];
if (i > start && second == nums[i - 1]) {
continue;
}
if (second + 2 * max < target) {
continue;
}
if (3 * second > target) {
break;
}
if (3 * second == target) {
if (nums[i + 2] == second) {
res.add(Arrays.asList(first, second, second, second));
}
break;
}
twoSum(nums, target - second, i + 1, res, first, second);
}
}
private void twoSum(int[] nums, int target, int start, List<List<Integer>> res, int first, int second) {
if (start > nums.length - 2) {
return;
}
int end = nums.length - 1;
int max = nums[end];
if (2 * nums[start] > target || 2 * max < target) {
return;
}
while (start < end) {
int sum = nums[start] + nums[end];
if (sum == target) {
res.add(Arrays.asList(first, second, nums[start], nums[end]));
while (start < end && nums[start] == nums[start + 1]) {
start++;
}
while (start < end && nums[end] == nums[end - 1]) {
end--;
}
start++;
end--;
} else if (sum < target) {
start++;
} else {
end--;
}
}
return;
}
}