文章目录
题目链接:
题目描述:
解法
解法一:排序+暴力枚举+利用
set
去重
解法二:排序+双指针
- 从左往右依次固定一个数
a
- 在
a
后面的区间里,利用"三数之和"找到三个数,使这三个数的和等于target-a
即可- 在上面一步的"三数之和"里面,我们先固定一个
b
,在b
后面的区间里面,利用"双指针"找到两个数,使这两个数的和等于target-a-b
即可。处理细节:
不重
- 双指针要跳过相同元素
b
要跳过相同元素a
要跳过相同元素不漏
双指针遇到合适的数继续往后走
C++ 算法代码:
cpp
class Solution
{
public:
vector<vector<int>> fourSum(vector<int>& nums, int target)
{
vector<vector<int>> ret;
// 1. 排序
sort(nums.begin(), nums.end());
// 2. 利用双指针解决问题
int n = nums.size();
for(int i = 0; i < n; ) // 固定数 a
{
// 利用 三数之和
for(int j = i + 1; j < n; ) // 固定数 b
{
// 双指针
int left = j + 1, right = n - 1;
long long aim = (long long)target - nums[i] - nums[j];//aim = target - a - b
while(left < right)
{
int sum = nums[left] + nums[right];
if(sum < aim) {
left++;
}
else if(sum > aim) {
right--;
}
else
{
ret.push_back({nums[i], nums[j], nums[left++],
nums[right--]});//ret数组存放最终结果
// 去重一
while(left < right && nums[left] == nums[left - 1]) {
left++;
}
while(left < right && nums[right] == nums[right + 1]) {
right--;
}
}
}
// 去重二
j++;
while(j < n && nums[j] == nums[j - 1]) {
j++;
}
}
// 去重三
i++;
while(i < n && nums[i] == nums[i - 1]) {
i++;
}
}
return ret;
}
};
图解
nums=[1,0,-1,0,-2,2]
target=0
n=6,i=0,j=1,left=2,right=5,aim=-1
left<right,sum=-1+2=1>aim,right--
left<right,sum=-1-2=-3<aim,left++
-
left<right,sum=0-2=-2<aim,left++
-
不满足循环条件,跳出
while
循环,进入去重2
,j++
-
n=6,i=0,j=2,left=3,right=5,aim=0
-
后面的步骤类似,就不多赘述了。