Skip to main content

3Sum

LeetCode 15 | Difficulty: Medium​

Medium

Problem Description​

Given an integer array nums, return all the triplets [nums[i], nums[j], nums[k]] such that i != j, i != k, and j != k, and nums[i] + nums[j] + nums[k] == 0.

Notice that the solution set must not contain duplicate triplets.

Example 1:

Input: nums = [-1,0,1,2,-1,-4]
Output: [[-1,-1,2],[-1,0,1]]
Explanation:
nums[0] + nums[1] + nums[2] = (-1) + 0 + 1 = 0.
nums[1] + nums[2] + nums[4] = 0 + 1 + (-1) = 0.
nums[0] + nums[3] + nums[4] = (-1) + 2 + (-1) = 0.
The distinct triplets are [-1,0,1] and [-1,-1,2].
Notice that the order of the output and the order of the triplets does not matter.

Example 2:

Input: nums = [0,1,1]
Output: []
Explanation: The only possible triplet does not sum up to 0.

Example 3:

Input: nums = [0,0,0]
Output: [[0,0,0]]
Explanation: The only possible triplet sums up to 0.

Constraints:

- `3 <= nums.length <= 3000`

- `-10^5 <= nums[i] <= 10^5`

Topics: Array, Two Pointers, Sorting


Approach​

Two Pointers​

Use two pointers to traverse the array, reducing the search space at each step. This avoids the need for nested loops, bringing complexity from O(nΒ²) to O(n) or O(n log n) if sorting is involved.

When to use

Array is sorted or can be sorted, and you need to find pairs/triplets that satisfy a condition.


Solutions​

Solution 1: C# (Best: 156 ms)​

MetricValue
Runtime156 ms
Memory48.2 MB
Date2021-11-09
Solution
public class Solution {
public IList<IList<int>> ThreeSum(int[] nums) {
IList<IList<int>> result = new List<IList<int>>();
if (nums.Length < 3)
{
return result;
}
Array.Sort(nums);
for (int i = 0; i < nums.Length - 2; i++)
{
if(i>0 && nums[i] == nums[i-1]) continue;
if(nums[i] > 0) break;
int left = i + 1;
int right = nums.Length - 1;
while (left < right)
{
int sum = nums[i] + nums[left] + nums[right];
if (sum == 0)
{
result.Add(new List<int> { 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 (sum < 0)
{
left++;
}
else
{
right--;
}
}
}

return result;
}
}
πŸ“œ 2 more C# submission(s)

Submission (2021-11-09) β€” 164 ms, 47.9 MB​

public class Solution {
public IList<IList<int>> ThreeSum(int[] nums) {
IList<IList<int>> result = new List<IList<int>>();
if (nums.Length < 3)
{
return result;
}
Array.Sort(nums);
for (int i = 0; i < nums.Length - 2; i++)
{
if(i>0 && nums[i] == nums[i-1]) continue;
int left = i + 1;
int right = nums.Length - 1;
while (left < right)
{
int sum = nums[i] + nums[left] + nums[right];
if (sum == 0)
{
result.Add(new List<int> { 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 (sum < 0)
{
left++;
}
else
{
right--;
}
}
}

return result;
}
}

Submission (2017-07-24) β€” 742 ms, N/A​

public class Solution {
public IList<IList<int>> ThreeSum(int[] nums) {
IList<IList<int>> result = new List<IList<int>>();
Array.Sort(nums);
for (int i = 0; i+2 < nums.Length; i++)
{
if(i>0 && nums[i]==nums[i-1]) continue;
int j = i + 1, k = nums.Length - 1;
int target = -nums[i];
while (j < k)
{
if (nums[j] + nums[k] == target)
{
result.Add(new List<int> { nums[i], nums[j], nums[k]});
j++;
k--;
while(j<k && nums[j] == nums[j-1]) j++;
while(j<k && nums[k] == nums[k+1]) k--;
}
else if (nums[j] + nums[k] > target)
{
k--;
}
else j++;
}
}
return result;
}
}

Complexity Analysis​

ApproachTimeSpace
Two Pointers$O(n)$$O(1)$
Sort + Process$O(n log n)$$O(1) to O(n)$

Interview Tips​

Key Points
  • Discuss the brute force approach first, then optimize. Explain your thought process.
  • Ask: "Can I sort the array?" β€” Sorting often enables two-pointer techniques.
  • LeetCode provides 3 hint(s) for this problem β€” try solving without them first.
πŸ’‘ Hints

Hint 1: So, we essentially need to find three numbers x, y, and z such that they add up to the given value. If we fix one of the numbers say x, we are left with the two-sum problem at hand!

Hint 2: For the two-sum problem, if we fix one of the numbers, say x, we have to scan the entire array to find the next number y, which is value - x where value is the input parameter. Can we change our array somehow so that this search becomes faster?

Hint 3: The second train of thought for two-sum is, without changing the array, can we use additional space somehow? Like maybe a hash map to speed up the search?