Difficulty: Medium · LeetCode 15
Problem
Find all unique triplets [nums[i], nums[j], nums[k]] such that i != j != k and nums[i] + nums[j] + nums[k] == 0.
Understanding the problem
Triplets must sum to zero and contain no duplicate triplets in output.
Intuition
Sort array. Fix index i, then use two pointers left and right to solve Two Sum II for remainder. Skip duplicate values.
Approach
Sort
nums.Loop
ifrom 0 to n-3. Skip ifnums[i] == nums[i-1].Run Two Pointers on
left = i+1,right = n-1.When match found, append triplet and advance both pointers past duplicate values.
Naive Solution — Brute Force
Triple nested loop + set of sorted tuples to eliminate duplicates.
class Solution:
def threeSum(self, nums):
result = set()
n = len(nums)
for i in range(n):
for j in range(i + 1, n):
for k in range(j + 1, n):
if nums[i] + nums[j] + nums[k] == 0:
result.add(
tuple(sorted(
[nums[i], nums[j], nums[k]]
))
)
return [list(x) for x in result]class Solution {
public:
vector<vector<int>> threeSum(vector<int>& nums) {
set<vector<int>> result;
int n = nums.size();
for (int i = 0; i < n; i++)
for (int j = i + 1; j < n; j++)
for (int k = j + 1; k < n; k++)
if (nums[i] + nums[j] + nums[k] == 0) {
vector<int> triplet = {nums[i], nums[j], nums[k]};
sort(triplet.begin(), triplet.end());
result.insert(triplet);
}
return vector<vector<int>>(result.begin(), result.end());
}
};class Solution {
public List<List<Integer>> threeSum(int[] nums) {
Set<List<Integer>> result = 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++)
if (nums[i] + nums[j] + nums[k] == 0) {
List<Integer> triplet = Arrays.asList(nums[i], nums[j], nums[k]);
Collections.sort(triplet);
result.add(triplet);
}
return new ArrayList<>(result);
}
}var threeSum = function(nums) {
const result = new Map();
const n = nums.length;
for (let i = 0; i < n; i++)
for (let j = i + 1; j < n; j++)
for (let k = j + 1; k < n; k++)
if (nums[i] + nums[j] + nums[k] === 0) {
const triplet = [nums[i], nums[j], nums[k]].sort((a, b) => a - b);
result.set(triplet.join(","), triplet);
}
return [...result.values()];
};Time: O(n³) · Space: O(n)
Optimized Code (Python 3)
class Solution:
def threeSum(self, nums):
nums.sort()
result = []
n = len(nums)
for i in range(n - 2):
if i > 0 and nums[i] == nums[i - 1]:
continue
left = i + 1
right = n - 1
while left < right:
total = (
nums[i]
+ nums[left]
+ nums[right]
)
if total == 0:
result.append([
nums[i],
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 < 0:
left += 1
else:
right -= 1
return resultclass Solution {
public:
vector<vector<int>> threeSum(vector<int>& nums) {
sort(nums.begin(), nums.end());
vector<vector<int>> result;
int n = nums.size();
for (int i = 0; i < n - 2; i++) {
if (i > 0 && nums[i] == nums[i - 1]) continue;
int left = i + 1, right = n - 1;
while (left < right) {
int total = nums[i] + nums[left] + nums[right];
if (total == 0) {
result.push_back({nums[i], nums[left], nums[right]});
left++;
right--;
while (left < right && nums[left] == nums[left - 1]) left++;
while (left < right && nums[right] == nums[right + 1]) right--;
} else if (total < 0) {
left++;
} else {
right--;
}
}
}
return result;
}
};class Solution {
public List<List<Integer>> threeSum(int[] nums) {
Arrays.sort(nums);
List<List<Integer>> result = new ArrayList<>();
int n = nums.length;
for (int i = 0; i < n - 2; i++) {
if (i > 0 && nums[i] == nums[i - 1]) continue;
int left = i + 1, right = n - 1;
while (left < right) {
int total = nums[i] + nums[left] + nums[right];
if (total == 0) {
result.add(Arrays.asList(nums[i], nums[left], nums[right]));
left++;
right--;
while (left < right && nums[left] == nums[left - 1]) left++;
while (left < right && nums[right] == nums[right + 1]) right--;
} else if (total < 0) {
left++;
} else {
right--;
}
}
}
return result;
}
}var threeSum = function(nums) {
nums.sort((a, b) => a - b);
const result = [];
const n = nums.length;
for (let i = 0; i < n - 2; i++) {
if (i > 0 && nums[i] === nums[i - 1]) continue;
let left = i + 1, right = n - 1;
while (left < right) {
const total = nums[i] + nums[left] + nums[right];
if (total === 0) {
result.push([nums[i], nums[left], nums[right]]);
left++;
right--;
while (left < right && nums[left] === nums[left - 1]) left++;
while (left < right && nums[right] === nums[right + 1]) right--;
} else if (total < 0) {
left++;
} else {
right--;
}
}
}
return result;
};Time: O(n²) · Aux Space: O(1)
Takeaway
Pattern — 3Sum = Sort + Fix One + Two Sum