题目
给定n个整数的一个数组S,S中是否有元素a,b,c,d满足 a+b+c+d = 0 ? 找出数组中所有满足加和为target的不同的三个数组合。
注意:(a,b,c)中的元素必须是非降序的排列方式(即a<=b<=c)
解决方案中给出的集合不能包含重复的三元组
例如,给定的数组S={1 0 -1 0 -2 2},并且target = 0。
解决方案集合是
{-1, 0, 0, 1}
{-2, -1, 1, 2}
{-2, 0, 0, 2}
解析
本题其实是第一题“两数之和”的拓展,可以先获得(a+b)和(c+d)的所有可能集合S-Com,那么在S-Com上再做一遍“两数之和”,问题就解决了。 最后再将求得解的集合根据(a+b)和(c+d)与S中的映射关系还原回来即可。
下面代码并没有给出S-com与S的反映射。(ps.觉得有点繁琐,不是当前算法的重点。。。)
代码
#include<iostream>
#include<vector>
#include <algorithm>
using namespace std;
vector< vector<int> > twoSum(vector<int>&num, int target){
sort(num.begin(), num.end());
int start =0, end = num.size()-1;
vector< vector<int> > result;
while(start < end){
int sum = num[start] + num[end];
if(sum == target){
vector<int> solution;
solution.push_back(num[start]);
solution.push_back(num[end]);
result.push_back(solution);
start++; end--;
//双指针扫描的去重
while(start<end && num[start] == num[start-1])
start++;//如果下一个元素与上一个元素相等,那么跳过
while(start<end && num[end] == num[end+1])
end--;//如果上一个元素和当前end相等,跳过这个
}
else if(sum < target)
start++;
else
end--;
}//end while
//下面是输出
vector< vector<int> >::iterator iter1;
for(iter1 = result.begin(); iter1 != result.end(); iter1++){
vector<int> vTemp = *iter1;
vector<int>::iterator iter2;
for(iter2 = vTemp.begin(); iter2 != vTemp.end(); iter2++){
cout<<*iter2<<" ";
}
cout<<endl;
}
return result;
}
void main(){
//numbers = {1 0 -1 0 -2 2}, target = 0
int nums[] = {1,0,-1,0,-2,2}; //在这里改变数组值
vector<int> v;
for(int i=0; i<6; i++){
for(int j=0; j<6; j++){
if(i != j){
v.push_back(nums[i] + nums[j]);
}
}
}
twoSum( v , 0); //调用函数,结束
}