# 4 Sum

Medium

Given an array`nums`ofn_integers and an integer`target`, are there elements_a,b,c, andd_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]
]``````

## Analysis

All K Sum problem can be divided into two problems:

• 2 Sum Problem

• Reduce K Sum problem to K – 1 Sum Problem

## Solution

Similar idea to 3 sum, basically reduce to 2sum, adding one more outer loop. And ALWAYS remember to skip duplicates.

Time - O(n^3), Space - O(1); (33 ms, faster than 78.15%)

``````class Solution {
public List<List<Integer>> fourSum(int[] nums, int target) {
List<List<Integer>> res = new ArrayList<>();
if (nums.length < 4) {
return res;
}
Arrays.sort(nums);

for (int i = 0; i < nums.length - 3; i++) {
if (i > 0 && nums[i] == nums[i - 1]) {
continue;
}
for (int j = i + 1; j < nums.length - 2; j++) {
if (j > i + 1 && nums[j] == nums[j - 1]) {
continue;
}
int t = target - nums[i] - nums[j];
int k = j + 1;
int l = nums.length - 1;
while (k < l) {
int sum = nums[k] + nums[l];
if (sum < t) {
k++;
} else if (sum > t) {
l--;
} else {
k++;
l--;

while (k < l && nums[k] == nums[k - 1]) {
k++;
}
while (k < l && nums[l] == nums[l + 1]) {
l--;
}
}
}
}
}
return res;
}
}``````

Generalized K Sum Approach:

``````class Solution {
public List<List<Integer>> fourSum(int[] nums, int target) {
Arrays.sort(nums);
return kSum(nums, 0, 4, target);
}

private List<List<Integer>> kSum (int[] nums, int start, int k, int target) {
int len = nums.length;
List<List<Integer>> res = new ArrayList<List<Integer>>();
if (k == 2) {
//two pointers from left and right
int left = start, right = len - 1;
while (left < right) {
int sum = nums[left] + nums[right];
if (sum == target) {
List<Integer> path = new ArrayList<Integer>();
left++;
right--;

while(left < right && nums[left] == nums[left - 1]) left++;
while(left < right && nums[right] == nums[right + 1]) right--;

} else if (sum < target) { //move left
left++;
} else { //move right
right--;
}
}
} else {
for(int i = start; i < len - (k - 1); i++) {
if(i > start && nums[i] == nums[i - 1]) continue;
List<List<Integer>> temp = kSum(nums, i + 1, k - 1, target - nums[i]);
for(List<Integer> t : temp) {
}
}
}
return res;
}
}``````

Another K Sum

``````public class Solution {
int len = 0;
public List<List<Integer>> fourSum(int[] nums, int target) {
len = nums.length;
Arrays.sort(nums);
return kSum(nums, target, 4, 0);
}
private ArrayList<List<Integer>> kSum(int[] nums, int target, int k, int index) {
ArrayList<List<Integer>> res = new ArrayList<List<Integer>>();
if (index >= len) {
return res;
}
if (k == 2) {
int i = index, j = len - 1;
while (i < j) {
//find a pair
if (target - nums[i] == nums[j]) {
List<Integer> temp = new ArrayList<>();
i++;
j--;
//skip duplication
while (i < j && nums[i] == nums[i - 1]) i++;
while (i < j && nums[j] == nums[j + 1]) j--;
} else if (target - nums[i] > nums[j]) {
//move left bound
i++;
} else {
//move right bound
j--;
}
}
} else {
for (int i = index; i < len - k + 1; i++) {
// Alternative: Skipping duplicates in the front
// if (i > index && nums[i] == nums[i - 1]) {
//    continue;
// }
//use current number to reduce k sum into k-1 sum
ArrayList<List<Integer>> temp = kSum(nums, target - nums[i], k - 1, i + 1);
if (temp != null) {
for (List<Integer> t : temp) {
}
}
//skip duplicated numbers
while (i < len - 1 && nums[i] == nums[i + 1]) {
i++;
}
}
}
return res;
}
}``````

Last updated