Given an array S of n integers, are there elements a, b, c in S such that a + b + c = 0? Find all unique triplets in the array which gives the sum of zero.
Note:
- Elements in a triplet (a,b,c) must be in non-descending order. (ie, a ≤ b ≤ c)
- The solution set must not contain duplicate triplets.
For example, given array S = {-1 0 1 2 -1 -4}, A solution set is: (-1, 0, 1) (-1, -1, 2)
思路:
the key idea is the same as the TwoSum
problem. When we fix the 1st
number,
the 2nd
and3rd
number
can be found following the same reasoning as TwoSum
.
The only difference is that, the TwoSum
problem of LEETCODE has a unique solution.
However, in ThreeSum
, we have multiple duplicate solutions that can be found. Most
of the OLE errors happened here because you could've ended up with a solution with so many duplicates.
The naive solution for the duplicates will be using the STL methods like below :
std::sort(res.begin(), res.end());
res.erase(unique(res.begin(), res.end()), res.end());
But according to my submissions, this way will cause you double your time consuming almostly.
A better approach is that, to jump over the number which has been scanned, no matter it is part of some solution or not.
If the three numbers formed a solution, we can safely ignore all the duplicates of them.
We can do this to all the three numbers such that we can remove the duplicates.
Here's my AC C++ Code: Runtime: 62
ms
class Solution {
public:
vector<vector<int> > threeSum(vector<int> &num) {
vector<vector<int> > res;
std::sort(num.begin(), num.end());
for (int i = 0; i < num.size(); i++) {
int target = -num[i];
int front = i + 1;
int rear = num.size() - 1;
while (front < rear) {
int sum = num[front] + num[rear];
// Finding answer which start from number num[i]
if (sum < target)
front++;
else if (sum > target)
rear--;
else
{
vector<int> triplet(3, 0);
triplet[0] = num[i];
triplet[1] = num[front];
triplet[2] = num[rear];
res.push_back(triplet);
// Processing duplicates of Number 2
// Rolling the front pointer to the next different number forwards
while (num[front] == triplet[1] && front < rear) front++;
// Processing duplicates of Number 3
// Rolling the rear pointer to the next different number backwards
while (num[rear] == triplet[2] && front < rear) rear--;
}
}
// Processing duplicates of Number 1
while (i + 1 < num.size() && num[i + 1] == num[i])
i++;
}
return res;
}
};