15. 3Sum
Medium
Given an array nums
of n integers, are there elements a, b, c in nums
such that a + b + c= 0? Find all unique triplets in the array which gives the sum of zero.
Note:
The solution set must not contain duplicate triplets.
Example:
Given array nums = [-1, 0, 1, 2, -1, -4],
A solution set is:
[
[-1, 0, 1],
[-1, -1, 2]
]
1. 首先对vector排序。
2. 依次不重复取出每一个数nums[i](如果取出重复的数一定会导致重复的三元组)。
3. 对剩余的数,转换成TwoSum问题,target=-nums[i]。
4. 设置双指针left=i+1和right=nums.size()-1。
5. 如果nums[left]+nums[right]==target,则记录,并且跳过所有邻近的相同元素。
6. 如果大于,right--;如果小于,left++。
//https://leetcode.com/problems/3sum/discuss/7628/Share-my-C%2B%2B-solutionvery-easy-to-understand
#include<iostream>
#include<vector>
#include<map>
#include<algorithm>
using namespace std;
vector<vector<int>> threeSum(vector<int>& nums) {
vector<vector<int>> ret;
int n = nums.size();
if (n < 3)
return ret;
sort(nums.begin(), nums.end());
int i = 0, left = 0, right = 0, target = 0;
for (i = 0; i < n - 2; ++i)
{
//nums has been sorted in ascending order,if nums[i]>0, there are must not such triplets in the rear
//thanks for lxyscls's advice
if (nums[i] > 0)
break;
if (i != 0 && nums[i] == nums[i - 1])
continue;
target = 0 - nums[i];
left = i + 1;
right = n - 1;
while (left < right)
{
if (nums[right] < 0)
break;
if ((nums[left] + nums[right]) == target)
{
vector<int> temp;
temp.push_back(nums[i]);
temp.push_back(nums[left]);
temp.push_back(nums[right]);
ret.push_back(temp);
while (left < right && nums[left + 1] == nums[left])
++left;
while (left < right && nums[right - 1] == nums[right])
--right;
++left;
--right;
}
else if ((nums[left] + nums[right]) < target)
++left;
else
--right;
}
}
return ret;
}
int main(void) {
int n, elem; vector<int> input;
while (cin >> n) {
if (!input.empty()) input.pop_back();
for (int i = 0; i<n; i++) {
cin >> elem;
input.push_back(elem);
}
vector<vector<int> > ans = threeSum(input);
for (int i = 0; i<int(ans.size()); i++) {
cout << ans[i][0] << " " << ans[i][1] << " " << ans[i][2] << endl;
}
}
return 0;
}