3Sum
LeetCode 15 | Difficulty: Mediumβ
MediumProblem 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.
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)β
| Metric | Value |
|---|---|
| Runtime | 156 ms |
| Memory | 48.2 MB |
| Date | 2021-11-09 |
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β
| Approach | Time | Space |
|---|---|---|
| Two Pointers | $O(n)$ | $O(1)$ |
| Sort + Process | $O(n log n)$ | $O(1) to O(n)$ |
Interview Tipsβ
- 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?