题目要求:
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)思路:这个问题可以退化成先找一个数a, 然后在剩下的集合中找两个数使它们的和为 target - a; 所以先将数组排序,然后顺次遍历, 使当前数位选中的数,再在剩余的集合中找到符合要求的两个数。
代码:
vector<vector<int> > threeSum(vector<int> &num)
{
sort(num.begin(), num.end());
// return DFS(num, 0, 3, 0);
ans.clear();
if(num.size() < 3)
return ans;
int count = num.size() - 2;
vector<int> triple(3, 0);
int current = num[0];
triple[0] = num[0];
//每次挑出一个数
for(size_t i = 0; i < count; ++i)
{
if(i && num[i] == current)
continue;
triple[0] = num[i];
int j = i + 1;
int k = num.size() - 1;
while(j < k)
{
int sum = triple[0] + num[j] + num[k];
if(sum == 0)
{
triple[1] = num[j];
triple[2] = num[k];
//因为都是按顺序找的所以出现重复也肯定是相邻的
if(ans.size() == 0 || triple != ans[ans.size() - 1])
ans.push_back(triple);
++j;
--k;
}
else if(sum > 0)
--k;
else
++j;
}
current = num[i];
}
return ans;
}
3-sum closest
题目要求:
Given an array S of n integers, find three integers in S such that the sum is closest to a given number, target. Return the sum of the three integers. You may assume that each input would have exactly one solution.
For example, given array S = {-1 2 1 -4}, and target = 1. The sum that is closest to the target is 2. (-1 + 2 + 1 = 2).思路与3 sum差不多,就是在找的过程中记录更新最小值。最后返回:
代码:
int threeSumClosest(vector<int> &num, int target)
{
if(num.size() < 3)
return abs(target);
sort(num.begin(), num.end());
int min_dist = numeric_limits<int>::max();
int res;
for(size_t i = 0; i < num.size(); ++i)
{
int j = i + 1, k = num.size() - 1;
int sum = 0;
while(j < k)
{
sum = num[i] + num[j] + num[k];
if(sum == target)
return sum;
else if(sum > target)
--k;
else
++j;
if(min_dist > abs(sum - target))
{
min_dist = abs(sum - target);
res = sum;
}
}
}
return res;
}
4-sum
Given an array S of n integers, are there elements a, b, c, and d in S such that a + b + c + d = target? Find all unique quadruplets in the array which gives the sum of target.
Note:
- Elements in a quadruplet (a,b,c,d) must be in non-descending order. (ie, a ≤ b ≤ c ≤ d)
- The solution set must not contain duplicate quadruplets.
For example, given array S = {1 0 -1 0 -2 2}, and target = 0. A solution set is: (-1, 0, 0, 1) (-2, -1, 1, 2) (-2, 0, 0, 2)思路: 与3-sum的做法差不多, 只是这次要先选两个数,然后再在剩下的数组中找到符合要求的另外两个数, 其实最后一步步退化成2-sum
代码:
vector<vector<int> > fourSum(vector<int> &num, int target) {
vector<vector<int> > ret;
set<vector<int> > unique_res;
if(num.size() < 4)
return ret;
sort(num.begin(), num.end());
vector<int> tmp_four(4, 0);
for(size_t i = 0; i < num.size(); ++i)
{
for(size_t j = i + 1; j < num.size(); ++j)
{
tmp_four[0] = num[i], tmp_four[1] = num[j];
int begin = j + 1, end = num.size() - 1;
while(begin < end)
{
int sum = tmp_four[0] + tmp_four[1] + num[begin] + num[end];
if(sum == target)
{
tmp_four[2] = num[begin];
tmp_four[3] = num[end];
unique_res.insert(tmp_four);
--end;
++begin;
}
else if(sum > target)
--end;
else
++begin;
}
}
}
for(set<vector<int> >::iterator iter = unique_res.begin(); iter != unique_res.end();
++iter)
ret.push_back(*iter);
return ret;
}
K-sum
思路与3-sum和4-sum,一步步退化成找2-sum
代码:
vector<vector<int> > DFS(vector<int>& num, int begin, int count, int sum)
{
// const int len = num.size();
set<int> visited;
vector<vector<int> > ret;
vector<int> triple;
if(count == 2)
{
int i = begin, j = num.size() - 1;
while(i < j)
{
if((num[i] + num[j]) == sum)
{
triple.clear();
triple.push_back(num[i]);
triple.push_back(num[j]);
ret.push_back(triple);
++i;
--j;
}
else if((num[i] + num[j]) > sum)
--j;
else
++i;
}
}
else
{
for(size_t i = begin; i < num.size(); ++i)
{
if(visited.count(num[i]) == 0)
{
visited.insert(num[i]);
vector<vector<int> > subset = DFS(num, i + 1, count - 1, sum - num[i]);
if(!subset.empty())
{
for(size_t j = 0; j < subset.size(); ++j)
subset[j].insert(subset[j].begin(), num[i]);
ret.insert(ret.end(), subset.begin(), subset.end());
}
}
}
}
return ret;
}