Description
4 Sum
Given an array nums of n integers, return an array of all the unique quadruplets [nums[a], nums[b], nums[c], nums[d]] such that:
0 <= a, b, c, d < na,b,c, anddare distinct.nums[a] + nums[b] + nums[c] + nums[d] == target
You may return the answer in any order.
Example 1:
Input: nums = [1,0,-1,0,-2,2], target = 0
Output: [[-2,-1,1,2],[-2,0,0,2],[-1,0,0,1]]
Example 2:
Input: nums = [2,2,2,2,2], target = 8
Output: [[2,2,2,2]]
Constraints:
1 <= nums.length <= 200-109 <= nums[i] <= 109-109 <= target <= 109
For 4Sum, the brute force method uses four nested loops, while the optimal solution sorts the array and combines two fixed loops with two pointers to achieve time complexity.
1. Brute Force Approach ()
Intuition
Check all possible quadruplets using four nested loops and insert sorted quadruplets into a set to eliminate duplicates.
public List<List<Integer>> fourSum(int[] nums, int target) {
Set<List<Integer>> resultSet = new HashSet<>();
int n = nums.length;
for (int i = 0; i < n; i++) {
for (int j = i + 1; j < n; j++) {
for (int k = j + 1; k < n; k++) {
for (int l = k + 1; l < n; l++) {
if ((long) nums[i] + nums[j] + nums[k] + nums[l] == target) {
List<Integer> quad = Arrays.asList(nums[i], nums[j], nums[k], nums[l]);
Collections.sort(quad);
resultSet.add(quad);
}
}
}
}
}
return new ArrayList<>(resultSet);
}
- Time Complexity:
- Space Complexity: worst-case to store quadruplets in the set.
2. Optimized Approach ()
Intuition: Fixed Outer Loops + Two Pointers
Think of 4Sum as extending 3Sum: fix the first two numbers (nums[i] and nums[j]) using loops, then solve the remaining two numbers using a left and right two-pointer search. Sorting first allows skipping duplicates naturally without extra set overhead.
4-Step Formula to Remember:
- Sort the array.
- Loop
ifrom0ton - 4. Skip duplicatenums[i]. - Loop
jfromi + 1ton - 3. Skip duplicatenums[j]. - Set
left = j + 1andright = n - 1. Moveleftforward ifsum < target,rightbackward ifsum > target. Whensum == target, record the answer and jump over duplicate values for both pointers.
public List<List<Integer>> fourSum(int[] nums, int target) {
List<List<Integer>> result = new ArrayList<>();
int n = nums.length;
if (n < 4) return result;
Arrays.sort(nums);
for (int i = 0; i < n - 3; i++) {
// Skip duplicates for 1st number
if (i > 0 && nums[i] == nums[i - 1]) continue;
for (int j = i + 1; j < n - 2; j++) {
// Skip duplicates for 2nd number
if (j > i + 1 && nums[j] == nums[j - 1]) continue;
int left = j + 1;
int right = n - 1;
while (left < right) {
// Cast to long to prevent integer overflow
long sum = (long) nums[i] + nums[j] + nums[left] + nums[right];
if (sum == target) {
result.add(Arrays.asList(nums[i], nums[j], nums[left], nums[right]));
// Skip duplicates for 3rd and 4th numbers
while (left < right && nums[left] == nums[left + 1]) left++;
while (left < right && nums[right] == nums[right - 1]) right--;
left++;
right--;
} else if (sum < target) {
left++;
} else {
right--;
}
}
}
}
return result;
}
- Time Complexity: — for sorting + for two nested loops with two pointers.
- Space Complexity: auxiliary memory (excluding the output list).