题目
给定n个整数的一个数组S,S中是否有元素a,b和c满足a+b+c+0 ? 找出数组中所有满足加和为0的不同的三个数组合。
注意:(a,b,c)中的元素必须是非降序的排列方式(即a<=b<=c)
解决方案中给出的集合不能包含重复的三元组
例如,给定的数组S={-1 0 1 2 -1 -4}
一个解决方案集合是
{-1, 0, 1}
{-1, -1 ,2}
解析
本题为第一天题目两数之和的拓展,把2个变量变成了3个变量。对于一般的拓展问题,要通过一些转换将其还原为已有的问题,才能更好的处理。
对于本题,我们稍微把等式修改一下, a + b + c = 0 => a + b = -c。
这个时候,问题就转换为,寻找两个变量 a 和 b ,使得其之和为 -c , 又回到了“两数之和”的问题。
因为题目提到了可能出现重复解的问题,所以要注意“去重”。这次的代码的变化也体现在去重的方面。
1. 双指针扫描的去重。例如对于 [-2, 0, 0, 2, 2]。我们期待的结果是[-2, 0, 2],如果不去重的话,结果就是[-2, 0, 2],[-2, 0, 2]。因为对于数组的处理是先排序的,所以本种除重是判断当前start指针值是否与前一个指针值相等,或者当前end指针值是否与后一个指针值相等,如果相等,那么就不予考虑。
2. 外层循环去重。 比如[-2, -2, -2, 0, 2],包含三个-2。当在循环中处理完第一个 -2 以后,后面的两个就没有必要进行重复处理了。
完整代码
#include <iostream>
#include <vector>
#include <map>
#include <algorithm>
using namespace std;
vector< vector<int> > threeSum(vector<int> &num){
sort(num.begin(), num.end());
vector< vector<int> > result;
int len = num.size();
for(int i=0; i<len; i++){
int target = 0 - num[i];
int start = i + 1, end = len - 1;
while(start < end){
if(num[start] + num[end] == target){
vector<int> solution;
solution.push_back(num[i]);
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 (num[start] + num[end] < target){
start++;
}
else{
end--;
}
}//end while
if(i<len-1){
//外层循环的去重
while(num[i] == num[i+1]) i++;
}
}//end for
//下面是输出
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()
{
int nums[] = {-1,0,1,2,-1,-4};//这里修改数组
vector<int> v;
for(int i=0; i<sizeof(nums) / 4; i++){
v.push_back(nums[i]);
}
threeSum(v);
}
学习笔记
- 对于int型数组,使用 sizeof() 对其求长度,需要除以4。 对于sizeof()的C++Reference是这样定义的:
The sizeof operator is a compile-time operator that returns the size, in bytes, of the argument passed to it.
sizeof(int): 4
sizeof(float): 4
sizeof(double): 8
sizeof(char): 1
sizeof()是求的字节长度,int字符是四个字节,所以在求int型数组的时候需要除以它的单位字节长度。
2.对于使用迭代器输出 两层vector 嵌套型数据结构内容,代码如下:
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;
}