LeetCode18-四数之和
18. 四数之和:
给你一个由 n 个整数组成的数组 nums ,和一个目标值 target 。请你找出并返回满足下述全部条件且不重复的四元组 [nums[a], nums[b], nums[c], nums[d]] :
- 0 <= a, b, c, d < n
- a、b、c 和 d 互不相同
- nums[a] + nums[b] + nums[c] + nums[d] == target
你可以按 任意顺序 返回答案 。
示例 1:
输入:nums = [1,0,-1,0,-2,2], target = 0
输出:[[-2,-1,1,2],[-2,0,0,2],[-1,0,0,1]]
示例 2:
输入:nums = [2,2,2,2,2], target = 8
输出:[[2,2,2,2]]
提示:
- 1 <= nums.length <= 200
- -10^9 <= nums[i] <= 10^9
- -10^9 <= target <= 10^9
解题思路1:
在解这道题之前先解决LeetCode15-三数之和以及LeetCode16-最接近的三数之和。
然后在来做这道题,注意数据范围,不难想到枚举前两个数a,b,后两个数用排序后尺取法进行优化。
注意,两个点:
- 要去重,也就是nums[a],nums[b],nums[c],nums[d]不能是同一组数(即使abcd有不同),注意示例2。
- 由于nums范围在1e9,所以4个数相加有可能超过int
class Solution {
public:
vector<vector<int> > fourSum(vector<int>& nums, int target) {
//set<vector<int> >s; //利用set去重
vector<vector<int> >ans;
int len=nums.size();
sort(nums.begin(),nums.end());
int l,r;
for(int i=0;i<len-3;++i) {
if(i!=0&&nums[i]==nums[i-1]) //去除重复的a
continue;
for(int j=i+1;j<len-2;++j) {
if(j!=i+1&&nums[j]==nums[j-1]) //去除重复的b
continue;
l=j+1,r=len-1;
while(l<r) {
long long sum=(long long)nums[i]+nums[j]+nums[l]+nums[r];
if(sum==target) {
vector<int>tmp{nums[i],nums[j],nums[l],nums[r]};
ans.push_back(tmp);
}
if(sum<=target){
l++;
while(l<r&&nums[l]==nums[l-1]) //去除重复的c
l++;
}
else{
r--;
while(l<r&&(r==len-1||nums[r]==nums[r+1])) //去除重复的d
r--;
}
}
}
}
return ans;
}
};
解题思路2:
利用set去重
class Solution {
public:
vector<vector<int> > fourSum(vector<int>& nums, int target) {
set<vector<int> >s; //利用set去重
vector<vector<int> >ans;
int len=nums.size();
sort(nums.begin(),nums.end());
int l,r;
for(int i=0;i<len-3;++i) {
for(int j=i+1;j<len-2;++j) {
l=j+1,r=len-1;
while(l<r) {
long long sum=(long long)nums[i]+nums[j]+nums[l]+nums[r];
if(sum==target) {
vector<int>tmp{nums[i],nums[j],nums[l],nums[r]};
s.insert(tmp);
}
if(sum<=target)
l++;
else
r--;
}
}
}
for(set<vector<int> >::iterator it=s.begin();it!=s.end();++it)
ans.push_back(*it);
return ans;
}
};