![](https://img-blog.csdnimg.cn/img_convert/0374d5233442c34ec763409c6f944c6b.png)
【题解】
双指针(时间复杂度:O(n^3))
注意:
定义二维数组存储结果集
对输入数组进行升序
两层for循环,两级剪枝,两级去重
(1)for循环, k = 0; i =k+1;都是nums.size();
(2)一级剪枝:不要判断nums[k] > target 就返回了,三数之和 可以通过 nums[i] > 0 就返回了,因为 0 已经是确定的数了,四数之和这道题目 target是任意值。比如:数组是[-4, -3, -2, -1],target是-10,不能因为-4 > -10而跳过。但是我们依旧可以去做剪枝,逻辑变成nums[i] > target && (nums[i] >=0 || target >= 0)就可以了。
二级剪枝:因为是两层for循环nums[k]+nums[i]为确定值,left和right作为双指针,找出四数之和为target的情况,所以用(nums[i] + nums[k] > target && nums[i] + nums[k] >= 0)
(3)nums[k]去重:(k > 0 && nums[k] == nums[k-1])
nums[i]去重:(i > k + 1 && nums[i] == nums[i-1])
nums[left]去重: while(right > left && nums[left] == nums[left+1]) left++;
nums[right]去重:while(right > left && nums[right] == nums[right-1]) right--;
class Solution {
public:
vector<vector<int>> fourSum(vector<int>& nums, int target) {
vector<vector<int>> result;//定义二维数组存储结果集
sort(nums.begin(), nums.end());//对输入数组进行升序
//外层for循环
for(int k = 0; k < nums.size(); k++){
//一级剪枝
if(nums[k] > target && nums[k] >= 0){
break;
}
//一级去重
if(k > 0 && nums[k] == nums[k-1]){
continue;
}
//内层for循环
for(int i = k + 1; i < nums.size(); i++){
//二级剪枝
if(nums[i] + nums[k] > target && nums[i] + nums[k] >= 0){
break;
}
//二级去重
if(i > k + 1 && nums[i] == nums[i-1]){
continue;
}
int left = i + 1;
int right = nums.size() - 1;
while(right > left){
//相加结果会溢出
if((long)nums[k] + nums[i] + nums[left] + nums[right] > target) right--;
else if((long)nums[k] + nums[i] + nums[left] + nums[right] < target) left++;
else{
result.push_back(vector<int>{nums[k], nums[i], nums[left], nums[right]});
// 对nums[left]和nums[right]去重
while(right > left && nums[left] == nums[left+1]) left++;
while(right > left && nums[right] == nums[right-1]) right--;
// 找到答案时,双指针同时收缩
left++;
right--;
}
}
}
}
return result;
}
};