Problem Statement

4Sum

You are given a list of numbers called nums and a target number. Your job is to find every group of four numbers from the list that adds up to the target. Each group uses four different spots in the list (four different positions), and you must not repeat the same group of four values twice in your answer. The trick we use is called two pointers. Imagine the numbers lined up in order on a ruler. You put one finger near the left end and one finger near the right end, then slide them toward each other depending on whether the sum is too small or too big. Here we lock the first two numbers in place with two loops, then use the two fingers to find the last two. We sort the list first so the numbers are in order, which is what makes the finger sliding and the duplicate skipping work.

mediumHash TableTwo PointersTwo PointersTime: O(n^3) · Space: O(n)

Signals to notice

find all unique quadruplets summing to targetextension of 3Sumavoid duplicates

Brute force first

Four nested loops. Checks every possible quadruplet. That instinct is useful because it follows the prompt literally, but it usually keeps revisiting work the problem is begging you to organize.

The key insight

Sort, fix two elements (i, j), two-pointer scan for the other two. Skip duplicates at each level. The goal is not to be clever for its own sake, but to remember the one relationship that keeps the solution grounded as you move forward.

Trace it on nums=[1,0,-1,0,-2,2], target=0

sort -> nums=[-2,-1,0,0,1,2], n=6, result=[]
i=0(-2), j=1(-1): left=2,right=5 total=-2-1+0+2=-1<0 -> left=3; total=-2-1+0+2=-1<0 -> left=4; total=-2-1+1+2=0 == -> add [-2,-1,1,2], left++,right-- -> left=5,right=4 stop
i=0(-2), j=2(0): left=3,right=5 total=-2+0+0+2=0 == -> add [-2,0,0,2], left++,right-- -> left=4,right=4 stop
i=0(-2), j=3(0): skip (j>i+1 and nums[3]==nums[2])
i=1(-1), j=2(0): left=3,right=5 total=-1+0+0+2=1>0 -> right=4; total=-1+0+0+1=0 == -> add [-1,0,0,1], left++,right-- -> left=4,right=3 stop
i=1,j=3: skip dup; i=1,j=4(1): left=5,right=5 no scan; i=2(0),j=3(0): left=4,right=5 total=0+0+1+2=3>0 no match
return [[-2,-1,1,2],[-2,0,0,2],[-1,0,0,1]]

What must stay true

Sort first, then fix outer two elements. For the remaining two, use the two-pointer technique on the sorted remainder. Duplicate skipping at every level prevents repeated quadruplets. As long as that statement keeps holding, you can trust the steps built on top of it.

Shape of the loop

sort(nums); n = len(nums)
for i in 0..n-4:                      # skip if i>0 and nums[i]==nums[i-1]
  for j in i+1..n-3:                  # skip if j>i+1 and nums[j]==nums[j-1]
    left, right = j+1, n-1
    while left < right:
      total = nums[i]+nums[j]+nums[left]+nums[right]
      if total==target: record [nums[i],nums[j],nums[left],nums[right]]; skip left/right dups; left++; right--
      elif total<target: left++
      else: right--
return result

Pseudocode only — the full worked solution lives in the Solution tab.

Easy way to go wrong

Not skipping duplicates at EVERY level — you need to skip at the i, j, left, AND right pointer levels to avoid duplicate quadruplets. Most mistakes here are not about syntax; they come from losing track of what your state, pointer, or structure is supposed to mean.

Two Pointers Pattern