题目描述
给定一个包含 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]
]
解题思路
去CSDN搜索“之和”,可以看到类似的题目。
本题在15、三数之和的基础上加了一层for
循环,思路是一样的。
- 排序 + 双指针:
- 使用四个指针
(a<b<c<d)
。固定最小的a
和b
在左边,c=b+1
,d=_size-1
。移动两个指针包夹求解。 保存使得nums[a]+nums[b]+nums[c]+nums[d]==target
的解。和偏大时d
左移,偏小时c
右移。c
和d
相遇时,表示以当前的a
和b
为最小值的解已经全部求得,b++
,进入下一轮b
循环,当b
循环结束后,a++
,进入下一轮a
循环。 即(a
在最外层循环,里面嵌套b
循环,再嵌套双指针c,d
包夹求解)。 - 要使用双指针的方法,排序是必须要做der~。 时间复杂度 。
- 上面的解法存在重复解的原因是因为移动指针时可能出现重复数字的情况。所以我们要确保移动指针后,
对应的数字要发生改变才行哦。
- 使用四个指针
参考代码
class Solution{
public:
vector<vector<int>> fourSum(vector<int>& nums, int target) {
vector<vector<int> > res;
if(nums.size()<4)
return res;
sort(nums.begin(),nums.end());
int a, b, c, d, _size = nums.size();
for(a = 0; a <= _size-4; a++){
if(a > 0 && nums[a] == nums[a-1])
continue; //确保nums[a] 改变了
for(b = a+1; b <= _size-3; b++){
if(b > a+1 && nums[b] == nums[b-1])
continue; //确保nums[b] 改变了
c = b + 1, d = _size - 1;
while(c < d){
if(nums[a]+nums[b]+nums[c]+nums[d] < target)
c++;
else if(nums[a]+nums[b]+nums[c]+nums[d] > target)
d--;
else{
res.push_back({nums[a], nums[b], nums[c], nums[d]});
while(c < d && nums[c+1]==nums[c]) //确保nums[c] 改变了
c++;
while(c < d&&nums[d-1]==nums[d]) //确保nums[d] 改变了
d--;
c++;
d--;
}
}
}
}
return res;
}
};