You are given an integer array nums of size n, 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, and d are distinct.nums[a] + nums[b] + nums[c] + nums[d] == targetYou may return the answer in any order.
Note: [1,0,3,2] and [3,0,1,2] are considered as same quadruplets.
Example 1:
Input: nums = [3,2,3,-3,1,0], target = 3
Output: [[-3,0,3,3],[-3,1,2,3]]Example 2:
Input: nums = [1,-1,1,-1,1,-1], target = 2
Output: [[-1,1,1,1]]Constraints:
1 <= nums.length <= 200-1,000,000,000 <= nums[i] <= 1,000,000,000-1,000,000,000 <= target <= 1,000,000,000Before attempting this problem, you should be comfortable with:
The simplest approach is to try all possible combinations of four distinct elements and check if their sum equals the target. To avoid duplicate quadruplets, we first sort the array and use a set to store unique results. While this guarantees correctness, checking every combination of four elements is extremely slow for larger inputs.
a < b < c < d.nums[a] + nums[b] + nums[c] + nums[d] == target.class Solution:
def fourSum(self, nums: List[int], target: int) -> List[List[int]]:
n = len(nums)
nums.sort()
res = set()
for a in range(n):
for b in range(a + 1, n):
for c in range(b + 1, n):
for d in range(c + 1, n):
if nums[a] + nums[b] + nums[c] + nums[d] == target:
res.add((nums[a], nums[b], nums[c], nums[d]))
return list(res)Where is the size of the array and is the number of quadruplets.
We can reduce one loop by using a hash map. After sorting, we fix the first three elements with nested loops and use the hash map to check if the fourth element exists. The hash map stores the count of each number, and we decrement counts as we iterate to avoid using the same element twice. This reduces complexity from O(n^4) to O(n^3) while still handling duplicates by skipping consecutive equal elements.
i, decrement its count and skip duplicates.j > i, decrement its count and skip duplicates.k > j, decrement its count and skip duplicates.fourth = target - nums[i] - nums[j] - nums[k].fourth exists in the map with count > 0, add the quadruplet.class Solution:
def fourSum(self, nums: List[int], target: int) -> List[List[int]]:
nums.sort()
count = defaultdict(int)
for num in nums:
count[num] += 1
res = []
for i in range(len(nums)):
count[nums[i]] -= 1
if i > 0 and nums[i] == nums[i - 1]:
continue
for j in range(i + 1, len(nums)):
count[nums[j]] -= 1
if j > i + 1 and nums[j] == nums[j - 1]:
continue
for k in range(j + 1, len(nums)):
count[nums[k]] -= 1
if k > j + 1 and nums[k] == nums[k - 1]:
continue
fourth = target - (nums[i] + nums[j] + nums[k])
if count[fourth] > 0:
res.append([nums[i], nums[j], nums[k], fourth])
for k in range(j + 1, len(nums)):
count[nums[k]] += 1
for j in range(i + 1, len(nums)):
count[nums[j]] += 1
return resWhere is the size of the array and is the number of quadruplets.
The two-pointer technique from 2Sum and 3Sum extends naturally to 4Sum. After sorting, we fix the first two elements with nested loops, then use two pointers to find pairs that complete the target sum. The left pointer starts just after the second fixed element, and the right pointer starts at the end. We move them inward based on whether the current sum is too small or too large. Skipping duplicates at each level ensures unique quadruplets.
i from 0 to n, skipping duplicates.i, iterate j from i + 1 to n, skipping duplicates.left = j + 1 and right = n - 1.left < right:left.right.class Solution:
def fourSum(self, nums: List[int], target: int) -> List[List[int]]:
nums.sort()
n = len(nums)
res = []
for i in range(n):
if i > 0 and nums[i] == nums[i - 1]:
continue
for j in range(i + 1, n):
if j > i + 1 and nums[j] == nums[j - 1]:
continue
left, right = j + 1, n - 1
while left < right:
total = nums[i] + nums[j] + nums[left] + nums[right]
if total == target:
res.append([nums[i], nums[j], nums[left], nums[right]])
left += 1
right -= 1
while left < right and nums[left] == nums[left - 1]:
left += 1
while left < right and nums[right] == nums[right + 1]:
right -= 1
elif total < target:
left += 1
else:
right -= 1
return resWe can generalize the approach to solve K-Sum for any K using recursion. The idea is to reduce the problem: for K > 2, we fix one element and recursively solve (K-1)-Sum. When K reaches 2, we use the two-pointer technique as the base case. This approach is flexible and can handle any value of K without changing the core logic.
kSum(k, start, target):k == 2): Use two pointers from start to find pairs summing to target.i from start, recursively call kSum(k - 1, i + 1, target - nums[i]).kSum(4, 0, target) and return the collected results.class Solution:
def fourSum(self, nums: List[int], target: int) -> List[List[int]]:
nums.sort()
res, quad = [], []
def kSum(k, start, target):
if k == 2:
l, r = start, len(nums) - 1
while l < r:
if nums[l] + nums[r] < target:
l += 1
elif nums[l] + nums[r] > target:
r -= 1
else:
res.append(quad + [nums[l], nums[r]])
l += 1
r -= 1
while l < r and nums[l] == nums[l - 1]:
l += 1
while l < r and nums[r] == nums[r + 1]:
r -= 1
return
for i in range(start, len(nums) - k + 1):
if i > start and nums[i] == nums[i - 1]:
continue
quad.append(nums[i])
kSum(k - 1, i + 1, target - nums[i])
quad.pop()
kSum(4, 0, target)
return resWhen summing four integers, the result can exceed the 32-bit integer range. Always use a 64-bit type (like long in Java/C++) for the sum calculation to avoid overflow.
// Wrong: may overflow
int sum = nums[i] + nums[j] + nums[left] + nums[right];
// Correct: use long to prevent overflow
long sum = (long)nums[i] + nums[j] + nums[left] + nums[right];When skipping duplicates, you must check against the previous element, not the next one. Also, the skip should only happen after processing the first occurrence, not before.
# Wrong: skips before processing first occurrence
if i > 0 and nums[i] == nums[i - 1]: # This is correct for outer loops
# Wrong for two-pointer: checking next instead of previous
while left < right and nums[left] == nums[left + 1]:
# Correct: skip after finding a match, check previous
while left < right and nums[left] == nums[left - 1]:The two-pointer technique only works on a sorted array. Forgetting to sort first will cause the algorithm to miss valid quadruplets or produce incorrect results.