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 < n
  • abc, and d are 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:

  1. Sort the array.
  2. Loop i from 0 to n - 4. Skip duplicate nums[i].
  3. Loop j from i + 1 to n - 3. Skip duplicate nums[j].
  4. Set left = j + 1 and right = n - 1. Move left forward if sum < target, right backward if sum > target. When sum == 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).