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: 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] ];
这题其实有两种公认的思路,一种就是简单的之前那种从k-sum不停降级,降到2sum,另一种就是偶数类问题可以不断分解为多个2-sum问题,然后用hash map 解决,后者时间上节省很多,但是中间数据的存储要花费很多的空间。
方法一:降级到夹逼,O(n^3)
vector<vector<int> > fourSum(vector<int> &num, int target) {
int n = num.size();
vector<vector<int> > res;
unordered_map<int, vector<pair<int, int> > >pairs;
pairs.reserve(n*n);
sort(num.begin(), num.end());
for(int i = 0; i < n; i++)
for(int j = i+1 ; j < n; j++)
pairs[num[i]+num[j]].push_back(make_pair(i,j));
for(int i = 0; i < n - 3; i++)
{
if(i != 0 && num[i] == num[i-1])continue;//防止第一个元素重复
for(int j = i+1; j < n - 2; j++)
{
if(j != i+1 && num[j] == num[j-1])continue;//防止第二个元素重复
if(pairs.find(target - num[i] - num[j]) != pairs.end())
{
vector<pair<int, int>> &sum2 = pairs[target - num[i] - num[j]];
bool isFirstPush = true;
for(int k = 0; k < sum2.size(); k++)
{
if(sum2[k].first <= j)continue;//保证所求的四元组的数组下标是递增的
if(isFirstPush || (res.back())[2] != num[sum2[k].first])
{
res.push_back(vector<int>{num[i], num[j], num[sum2[k].first],
num[sum2[k].second]});
isFirstPush = false;
}
}
}
}
}
return res;
}
方法二的话,笔者自己还没想到怎么解决一些重复问题,待更中。。。