题目来源:链接: [https://leetcode-cn.com/problems/4sum/submissions/]
18. 四数之和
1.问题描述
给定一个包含 n 个整数的数组 nums 和一个目标值 target,判断 nums 中是否存在四个元素 a,b,c 和 d ,使得 a + b + c + d 的值与 target 相等?找出所有满足条件且不重复的四元组。
注意:
答案中不可以包含重复的四元组。
示例::
给定数组 nums = [1, 0, -1, 0, -2, 2],和 target = 0。
满足要求的四元组集合为:
[
[-1, 0, 0, 1],
[-2, -1, 1, 2],
[-2, 0, 0, 2]
]
2.我的解决方案
medium 类型题目。
类似题目: 两数和 、三数和 、 四数相加。
题目解析:
方法1. 暴力枚举法(不仅要遍历4次,而且要判断是否重复,时间复杂度太高)。
方法2. 首先排序,接着将四数之和转化为三数,再三数变成两数和,两数之和直接套用《两数之和2》的题,最后注意去重。
方法2AC代码如下:
class Solution {
public:
vector<vector<int>> fourSum(vector<int>& nums, int target) {
vector<vector<int>> res;
sort(nums.begin(), nums.end());
if(nums.empty()) return res;
for(int z = 0; z < nums.size(); ++z) {
if(z > 0 && nums[z] == nums[z-1]) continue;
int newTarget1 = target - nums[z]; //将四数和 转换成 3 数和
for(int k = z + 1; k < nums.size(); ++k) {
if(k > z + 1 && nums[k] == nums[k-1]) continue;
int newTarget2 = newTarget1 - nums[k]; //三数变两数
int i = k +1, j = nums.size() - 1;
while(i < j) {
if(nums[i] + nums[j] == newTarget2) {
res.push_back({nums[z], nums[k], nums[i], nums[j]});
while(i < j && nums[i] == nums[i+1]) ++i; //去重复
while(i < j && nums[j] == nums[j-1]) --j;
++i;
--j;
}
else if(nums[i] + nums[j] < newTarget2){
++i;
}
else{
--j;
}
}
}
}
return res;
}
};
3.大神们的解决方案
先留着等会看。。。
class Solution {
public:
vector<vector<int>> fourSum(vector<int>& nums, int target) {
vector<vector<int>> ans;
vector<int>tmp;
sort(nums.begin(), nums.end());
int len = nums.size();
for(int i = 0; i < len - 3; i++) {
if(i != 0 && nums[i] == nums[i-1]) continue;
if(nums[i] + nums[len-1] + nums[len-2] + nums[len-3] < target) continue;
if(nums[i] + nums[i+1] + nums[i+2] + nums[i+3] > target) break;
for(int j = i + 1; j < len - 2; j++) {
if(j != i + 1 && nums[j] == nums[j-1]) continue;
if(nums[i] + nums[len-1] + nums[len-2] + nums[j] < target) continue;
if(nums[i] + nums[j] + nums[j+1] + nums[j+2] > target) break;
int l = j + 1, r = len - 1, sum;
while(l < r) {
sum = nums[i] + nums[l] + nums[r] + nums[j];
if(sum > target) r--;
else if(sum < target) l++;
else {
tmp.clear();
tmp.push_back(nums[i]);
tmp.push_back(nums[j]);
tmp.push_back(nums[l]);
tmp.push_back(nums[r]);
ans.push_back(tmp);
while(l + 1 < r && nums[l] == nums[l+1]) l++;
l++;
}
}
}
}
return ans;
}
};
4.我的收获
继续努力。。。
2019/4/22 胡云层 于南京 62