题目:
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)
程序:
方法一:
哈希表,可减少一个循环,降低时间复杂度,同two-sum
class Solution {
public:
vector<vector<int> > threeSum(vector<int> &num) {
vector<vector<int>> res;
vector<int> v;
set<vector<int>> s;
if (num.size() == 0)
return res;
map<int, int> m;
sort(num.begin(), num.end());
for (int i = 0; i < num.size(); i++)
m[num[i]] = i;
for (int i = 0; i < num.size()-1; i++)
for (int j = i + 1; j < num.size();j++)
if (m.find(-(num[i] + num[j])) != m.end() && m[-(num[i] + num[j])] > j)
{
v.push_back(num[i]);
v.push_back(num[j]);
v.push_back(-(num[i] + num[j]));
s.insert(v);
v.clear();
}
copy(s.begin(),s.end(),back_inserter(res));
return res;
}
};
方法二:
双指针,同时逼近,同container-with-most-water
class Solution {
public:
vector<vector<int> > threeSum(vector<int> &num) {
//数组排序(小-->大)
sort(num.begin(), num.end());
//结果集合
vector<vector<int>> ans;
//先依次取出一个数,转换为 2 数求和问题
for (int i = 0; i < num.size(); i++){
if ( i == 0 || num[i] != num[i-1]){//防止重复
//定义左右指针
int left = i + 1, right = num.size() - 1;
// 2 数求和问题,固定left, 找出最大的right
while (left < right){
//right 左移, 减小 num[right] 的值
while (left < right && num[i] + num[left] + num[right] > 0) right --;
if (left < right && num[i] + num[left] + num[right] == 0){
//保存当前结果
vector<int> temp(3);
temp[0] = num[i];
temp[1] = num[left];
temp[2] = num[right];
//保存到最终的结果中
ans.push_back(temp);
//右移 left (去除重复)
while (left < right && num[left] == temp[1]) left ++;
} else { // num[i] + num[left] + num[right] < 0的情况,left右移,增大num[left]的值
left++;
}
}
}
}
return ans;
}
};