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.
做法1:基于3sum的做法,嵌个套找每个数对应的3sum即可,用时O(N^3).
vector<vector<int>> fourSum(vector<int>& nums, int target) {
sort(nums.begin(),nums.end());
int n=nums.size();
vector<vector<int>> anss;
unordered_map<int,int>check;
for(int k=0;k<n;k++){
if(check.find(nums[k])!=check.end())continue;
check[nums[k]]=k;
int aims=target-nums[k];
unordered_map<int,int> check1;
unordered_map<int,int> check2;
for(int i=k+1;i<n;i++){
if(check1.find(nums[i])!=check1.end())continue;
check1[nums[i]]=i;
int tar=aims-nums[i];
int l=i+1;
int h=n-1;
check2.clear();
while(l<h){
if(check2.find(nums[l])!=check2.end()&&check2.find(nums[h])!=check2.end()){
l++;h--;
continue;
}
int temp=nums[l]+nums[h];
if(temp==tar){
vector<int> tmp;
tmp.push_back(nums[k]);
tmp.push_back(nums[i]);
tmp.push_back(nums[l]);
tmp.push_back(nums[h]);
anss.push_back(tmp);
check2[nums[l]]=l;
check2[nums[h]]=h;
l++;h--;
}
if(temp>tar)h--;
if(temp<tar)l++;
}
}
}
return anss;
}
做法2:将所有2sum的结果找出来保存到新的位置,然后从中再找一次2sum,用时O(N^2+N)=O(N^2)。需要注意的是,两个2sum可能有相同的加数因子,所以需要记录下标,不要使用具有相同加数因子的2sum来求4sum。但是其实要记录下标也很麻烦,因为每种2sum和对应的两个加数可能不同,我们需要把他们都记下来。进行第二次2sum比较的时候,从两个2sum中找出所有的组合,这些组合都等于target,然后再比较下标是否有重复……最后还要擦除重复,着实是非常麻烦了……所以虽然看上去很快,但是做了许多复杂的操作之后,速度也没怎么快……
class Solution {
public:
vector<vector<int>> fourSum(vector<int>& nums, int target) {
unordered_map<int,vector<vector<int>>>index;//保存所有2sum组合的下标
unordered_map<int,vector<vector<int>>>adds;//保存所有2sum组合的两个加数
int n=nums.size();
vector<vector<int>> anss;
vector<int> newNums;//保存所有的2sum
for(int i=0;i<n;i++){
for(int j=i+1;j<n;j++){
int sum2=nums[i]+nums[j];
newNums.push_back(sum2);
index[sum2].push_back({i,j});
adds[sum2].push_back({nums[i],nums[j]});
}
}
sort(newNums.begin(),newNums.end());
int m=newNums.size();
int l=0,h=m-1,a,b,c,d;
while(l<h){
int sum4=newNums[l]+newNums[h];
if(sum4==target){
for(int i=0;i<index[newNums[l]].size();i++){
a=index[newNums[l]][i][0];
b=index[newNums[l]][i][1];
for(int j=0;j<index[newNums[h]].size();j++){
c=index[newNums[h]][j][0];
d=index[newNums[h]][j][1];
if(a!=c&&a!=d&&b!=c&&b!=d){
vector<int>tmp;
tmp.push_back(adds[newNums[l]][i][0]);
tmp.push_back(adds[newNums[l]][i][1]);
tmp.push_back(adds[newNums[h]][j][0]);
tmp.push_back(adds[newNums[h]][j][1]);
sort(tmp.begin(),tmp.end());
anss.push_back(tmp);
}
}
}
l++;h--;
}
if(sum4<target)l++;
if(sum4>target)h--;
}
sort(anss.begin(),anss.end());
anss.erase(unique(anss.begin(),anss.end()),anss.end());
return anss;
}
};