问题描述:Given an array S of n integers, are there elements a, b, c, and d in S such that a + b + c + d = target? Find all unique quadruplets in the array which gives the sum of target.
Note: The solution set must not contain duplicate quadruplets.
For example, given array S = [1, 0, -1, 0, -2, 2], and target = 0.
A solution set is:
[
[-1, 0, 0, 1],
[-2, -1, 1, 2],
[-2, 0, 0, 2]
]
由于之前已经做过了2Sum和3Sum的题目了,所以这里的算法也就是可以直接基于3Sum,然后再给一些细节优化,就可以得到一个比较高效的算法。给定一个动态数组vector
和目标值int target
,我们需要从数组中找到i1,i2,i3,i4
,满足nums[i1]+nums[i2]+nums[i3]+nums[i4]=target
.
(1)首先,若数组长度小于4直接返回空的答案,否则,使用sort()函数对数组nums进行排序:
int len = nums.size();
vector<vector<int>> result;
if (nums.size() < 4) return result;
sort(nums.begin(), nums.end());
(2)使用for循环遍历i1:
for (int i1 = 0; i1 < len - 3; ++i1)
(3)这里我们可以考虑优化操作,即当nums[i1] + nums[i1 + 1] + nums[i1 + 2] + nums[i1 + 3] > target
,此时无论i2、i3、i4如何取值都不会满足条件,所以可以直接使用break语句;当nums[i1] + nums[len - 3] + nums[len - 2] + nums[len - 1] < target
,此时只能继续增大i1,所以可以使用continue语句:
if (nums[i1] + nums[i1 + 1] + nums[i1 + 2] + nums[i1 + 3]>target) break;
if (nums[i1] + nums[len - 3] + nums[len - 2] + nums[len - 1]<target) continue;
(4)接着在i1的循环内,使用for循环遍历i2:
for (int i2 = i1 + 1; i2 < len - 2; ++i2)
(5)同样参考第(3)步的优化方法:
if (nums[i1] + nums[i2] + nums[i2 + 1] + nums[i2 + 2]>target) break;
if (nums[i1] + nums[i2] + nums[len - 2] + nums[len - 1]<target) continue;
(6)有了i1、i2,然后就是基于2Sum的算法求解,并且使用函数isExist()判断result内是否有重复的结果,若没有则把结果存于result中:
int i3 = i2 + 1, i4 = len - 1;
while (i3 < i4)
{
if (nums[i1] + nums[i2] + nums[i3] + nums[i4] < target) ++i3;
else if (nums[i1] + nums[i2] + nums[i3] + nums[i4] > target) --i4;
else
{
vector<int> tmp; tmp.push_back(nums[i1]); tmp.push_back(nums[i2]); tmp.push_back(nums[i3]); tmp.push_back(nums[i4]);
if (result.empty()) result.push_back(tmp);
else if(!isExist(result,tmp)) result.push_back(tmp);
++i3; --i4;
}
}
(7)最后返回结果:return result;
#include
#include
#include
using namespace std;
bool isExist(vector<vector<int>>& result, vector<int> &tmp)
{
for (int i = 0; i < result.size(); ++i)
if (result[i] == tmp) return true;
return false;
}
vector<vector<int>> fourSum(vector<int>& nums, int target)
{
int len = nums.size();
vector<vector<int>> result;
if (nums.size() < 4) return result;
sort(nums.begin(), nums.end());
for (int i1 = 0; i1 < len - 3; ++i1)
{
if (nums[i1] + nums[i1 + 1] + nums[i1 + 2] + nums[i1 + 3]>target) break;
if (nums[i1] + nums[len - 3] + nums[len - 2] + nums[len - 1]continue;
for (int i2 = i1 + 1; i2 < len - 2; ++i2)
{
if (nums[i1] + nums[i2] + nums[i2 + 1] + nums[i2 + 2]>target) break;
if (nums[i1] + nums[i2] + nums[len - 2] + nums[len - 1]continue;
int i3 = i2 + 1, i4 = len - 1;
while (i3 < i4)
{
if (nums[i1] + nums[i2] + nums[i3] + nums[i4] < target) ++i3;
else if (nums[i1] + nums[i2] + nums[i3] + nums[i4] > target) --i4;
else
{
vector<int> tmp; tmp.push_back(nums[i1]); tmp.push_back(nums[i2]); tmp.push_back(nums[i3]); tmp.push_back(nums[i4]);
if(!isExist(result,tmp)) result.push_back(tmp);
++i3; --i4;
}
}
}
}
return result;
}
int main()
{
int arr[] = { 1, 0, -1, 0, -2, 2 }, target = 0;
vector<int> nums(arr, arr + 6);
vector<vector<int>> result;
result = fourSum(nums, target);
for (int i = 0; i < result.size(); ++i)
{
for (int j = 0; j < result[i].size(); ++j)
cout << result[i][j] << " ";
cout << endl;
}
return 0;
}