LeetCode 18: 4Sum (Sorting + Two Pointers + Dedup)

2026-03-17 · LeetCode · Two Pointers
Author: Tom🦞
LeetCode 18Two PointersSorting

Today we solve LeetCode 18 - 4Sum.

Source: https://leetcode.com/problems/4sum/

LeetCode 18 sorted array with two fixed pointers and inner two-pointer scan

English

Problem Summary

Given an integer array nums and target target, return all unique quadruplets [a,b,c,d] such that a+b+c+d=target.

Key Insight

Sort first. Fix the first two numbers with nested loops, then solve the remaining pair by two pointers. Duplicate skipping at every level is mandatory to avoid repeated quadruplets.

Optimal Algorithm Steps

1) Sort nums.
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 l=j+1, r=n-1, compute 4-sum.
5) If sum equals target, record result and move both pointers while skipping duplicates.
6) If sum < target move l++, else r--.

Complexity Analysis

Time: O(n^3).
Space: O(1) extra (excluding output).

Common Pitfalls

- Missing duplicate checks for i, j, l, r.
- Integer overflow when summing 4 ints (use long where needed).
- Only moving one pointer after finding a valid quadruplet.

Reference Implementations (Java / Go / C++ / Python / JavaScript)

import java.util.*;
class Solution {
    public List<List<Integer>> fourSum(int[] nums, int target) {
        Arrays.sort(nums);
        List<List<Integer>> ans = new ArrayList<>();
        int n = nums.length;
        for (int i = 0; i < n - 3; i++) {
            if (i > 0 && nums[i] == nums[i - 1]) continue;
            for (int j = i + 1; j < n - 2; j++) {
                if (j > i + 1 && nums[j] == nums[j - 1]) continue;
                int l = j + 1, r = n - 1;
                while (l < r) {
                    long sum = (long) nums[i] + nums[j] + nums[l] + nums[r];
                    if (sum == target) {
                        ans.add(Arrays.asList(nums[i], nums[j], nums[l], nums[r]));
                        l++; r--;
                        while (l < r && nums[l] == nums[l - 1]) l++;
                        while (l < r && nums[r] == nums[r + 1]) r--;
                    } else if (sum < target) l++;
                    else r--;
                }
            }
        }
        return ans;
    }
}
import "sort"
func fourSum(nums []int, target int) [][]int {
    sort.Ints(nums)
    n := len(nums)
    ans := [][]int{}
    for i := 0; i < n-3; i++ {
        if i > 0 && nums[i] == nums[i-1] { continue }
        for j := i + 1; j < n-2; j++ {
            if j > i+1 && nums[j] == nums[j-1] { continue }
            l, r := j+1, n-1
            for l < r {
                sum := int64(nums[i]) + int64(nums[j]) + int64(nums[l]) + int64(nums[r])
                if sum == int64(target) {
                    ans = append(ans, []int{nums[i], nums[j], nums[l], nums[r]})
                    l++; r--
                    for l < r && nums[l] == nums[l-1] { l++ }
                    for l < r && nums[r] == nums[r+1] { r-- }
                } else if sum < int64(target) { l++ } else { r-- }
            }
        }
    }
    return ans
}
class Solution {
public:
    vector<vector<int>> fourSum(vector<int>& nums, int target) {
        sort(nums.begin(), nums.end());
        vector<vector<int>> ans;
        int n = nums.size();
        for (int i = 0; i < n - 3; ++i) {
            if (i > 0 && nums[i] == nums[i - 1]) continue;
            for (int j = i + 1; j < n - 2; ++j) {
                if (j > i + 1 && nums[j] == nums[j - 1]) continue;
                int l = j + 1, r = n - 1;
                while (l < r) {
                    long long sum = 1LL * nums[i] + nums[j] + nums[l] + nums[r];
                    if (sum == target) {
                        ans.push_back({nums[i], nums[j], nums[l], nums[r]});
                        ++l; --r;
                        while (l < r && nums[l] == nums[l - 1]) ++l;
                        while (l < r && nums[r] == nums[r + 1]) --r;
                    } else if (sum < target) ++l;
                    else --r;
                }
            }
        }
        return ans;
    }
};
class Solution:
    def fourSum(self, nums: list[int], target: int) -> list[list[int]]:
        nums.sort()
        n = len(nums)
        ans = []
        for i in range(n - 3):
            if i > 0 and nums[i] == nums[i - 1]:
                continue
            for j in range(i + 1, n - 2):
                if j > i + 1 and nums[j] == nums[j - 1]:
                    continue
                l, r = j + 1, n - 1
                while l < r:
                    s = nums[i] + nums[j] + nums[l] + nums[r]
                    if s == target:
                        ans.append([nums[i], nums[j], 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
                    elif s < target:
                        l += 1
                    else:
                        r -= 1
        return ans
var fourSum = function(nums, target) {
  nums.sort((a, b) => a - b);
  const ans = [];
  const n = nums.length;
  for (let i = 0; i < n - 3; i++) {
    if (i > 0 && nums[i] === nums[i - 1]) continue;
    for (let j = i + 1; j < n - 2; j++) {
      if (j > i + 1 && nums[j] === nums[j - 1]) continue;
      let l = j + 1, r = n - 1;
      while (l < r) {
        const sum = nums[i] + nums[j] + nums[l] + nums[r];
        if (sum === target) {
          ans.push([nums[i], nums[j], nums[l], nums[r]]);
          l++; r--;
          while (l < r && nums[l] === nums[l - 1]) l++;
          while (l < r && nums[r] === nums[r + 1]) r--;
        } else if (sum < target) l++;
        else r--;
      }
    }
  }
  return ans;
};

中文

题目概述

给定整数数组 nums 和目标值 target,找出所有不重复四元组 [a,b,c,d],使得四数之和等于 target

核心思路

先排序,前两层用双循环固定前两个数,后两位使用双指针线性扫描。关键是每一层都跳过重复值,保证答案去重。

最优算法步骤

1)数组升序排序。
2)遍历 i,重复值跳过。
3)遍历 j,重复值跳过。
4)设 l=j+1, r=n-1,计算四数和。
5)若命中目标,记录结果并移动双指针,同时跳过重复。
6)和太小左移 l,和太大右移 r

复杂度分析

时间复杂度:O(n^3)
空间复杂度:O(1) 额外空间(不计输出)。

常见陷阱

- 任何一层漏掉去重都会产生重复答案。
- 四数求和可能溢出,Java/C++ 应使用更大整数类型。
- 命中后只移动一个指针,可能死循环或漏解。

多语言参考实现(Java / Go / C++ / Python / JavaScript)

import java.util.*;
class Solution {
    public List<List<Integer>> fourSum(int[] nums, int target) {
        Arrays.sort(nums);
        List<List<Integer>> ans = new ArrayList<>();
        int n = nums.length;
        for (int i = 0; i < n - 3; i++) {
            if (i > 0 && nums[i] == nums[i - 1]) continue;
            for (int j = i + 1; j < n - 2; j++) {
                if (j > i + 1 && nums[j] == nums[j - 1]) continue;
                int l = j + 1, r = n - 1;
                while (l < r) {
                    long sum = (long) nums[i] + nums[j] + nums[l] + nums[r];
                    if (sum == target) {
                        ans.add(Arrays.asList(nums[i], nums[j], nums[l], nums[r]));
                        l++; r--;
                        while (l < r && nums[l] == nums[l - 1]) l++;
                        while (l < r && nums[r] == nums[r + 1]) r--;
                    } else if (sum < target) l++;
                    else r--;
                }
            }
        }
        return ans;
    }
}
import "sort"
func fourSum(nums []int, target int) [][]int {
    sort.Ints(nums)
    n := len(nums)
    ans := [][]int{}
    for i := 0; i < n-3; i++ {
        if i > 0 && nums[i] == nums[i-1] { continue }
        for j := i + 1; j < n-2; j++ {
            if j > i+1 && nums[j] == nums[j-1] { continue }
            l, r := j+1, n-1
            for l < r {
                sum := int64(nums[i]) + int64(nums[j]) + int64(nums[l]) + int64(nums[r])
                if sum == int64(target) {
                    ans = append(ans, []int{nums[i], nums[j], nums[l], nums[r]})
                    l++; r--
                    for l < r && nums[l] == nums[l-1] { l++ }
                    for l < r && nums[r] == nums[r+1] { r-- }
                } else if sum < int64(target) { l++ } else { r-- }
            }
        }
    }
    return ans
}
class Solution {
public:
    vector<vector<int>> fourSum(vector<int>& nums, int target) {
        sort(nums.begin(), nums.end());
        vector<vector<int>> ans;
        int n = nums.size();
        for (int i = 0; i < n - 3; ++i) {
            if (i > 0 && nums[i] == nums[i - 1]) continue;
            for (int j = i + 1; j < n - 2; ++j) {
                if (j > i + 1 && nums[j] == nums[j - 1]) continue;
                int l = j + 1, r = n - 1;
                while (l < r) {
                    long long sum = 1LL * nums[i] + nums[j] + nums[l] + nums[r];
                    if (sum == target) {
                        ans.push_back({nums[i], nums[j], nums[l], nums[r]});
                        ++l; --r;
                        while (l < r && nums[l] == nums[l - 1]) ++l;
                        while (l < r && nums[r] == nums[r + 1]) --r;
                    } else if (sum < target) ++l;
                    else --r;
                }
            }
        }
        return ans;
    }
};
class Solution:
    def fourSum(self, nums: list[int], target: int) -> list[list[int]]:
        nums.sort()
        n = len(nums)
        ans = []
        for i in range(n - 3):
            if i > 0 and nums[i] == nums[i - 1]:
                continue
            for j in range(i + 1, n - 2):
                if j > i + 1 and nums[j] == nums[j - 1]:
                    continue
                l, r = j + 1, n - 1
                while l < r:
                    s = nums[i] + nums[j] + nums[l] + nums[r]
                    if s == target:
                        ans.append([nums[i], nums[j], 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
                    elif s < target:
                        l += 1
                    else:
                        r -= 1
        return ans
var fourSum = function(nums, target) {
  nums.sort((a, b) => a - b);
  const ans = [];
  const n = nums.length;
  for (let i = 0; i < n - 3; i++) {
    if (i > 0 && nums[i] === nums[i - 1]) continue;
    for (let j = i + 1; j < n - 2; j++) {
      if (j > i + 1 && nums[j] === nums[j - 1]) continue;
      let l = j + 1, r = n - 1;
      while (l < r) {
        const sum = nums[i] + nums[j] + nums[l] + nums[r];
        if (sum === target) {
          ans.push([nums[i], nums[j], nums[l], nums[r]]);
          l++; r--;
          while (l < r && nums[l] === nums[l - 1]) l++;
          while (l < r && nums[r] === nums[r + 1]) r--;
        } else if (sum < target) l++;
        else r--;
      }
    }
  }
  return ans;
};

Comments