题目:Given an array S of n integers, are there elements a, b, c in S such that a + b + c = 0? Find all unique triplets in the array which gives the sum of zero.Note:
- Elements in a triplet (a,b,c) must be in non-descending order. (ie, a ≤ b ≤ c)
- The solution set must not contain duplicate triplets.
For example, given array S = {-1 0 1 2 -1 -4},
A solution set is:
(-1, 0, 1)
(-1, -1, 2)
思路:由于先做过这一问题《找出序列中求和最接近于target的三个数 3Sum Closest》。所以思路很明确,就是先固定三个数中最左边的那个数。然后再寻找另外两个数。时间复杂度为O(n*logn + n**2)。于是很快写出的第一版代码。可是,超时了!
代码一:
class Solution {
public:
vector<vector<int> > threeSum(vector<int> &num) {
int n = num.size();
vector<vector<int> > result;
sort(num.begin(), num.end());//先排序
int k, i, j, cur;
for(k=0;k<n-2;k++)
{
i = k+1;
j = n-1;
while(i<j)
{
cur = num[i] + num[j] + num[k];
if(cur > 0)
j--;
else if(cur < 0)
i++;
else
{
vector<int> tmp;
tmp.push_back(num[k]);
tmp.push_back(num[i]);
tmp.push_back(num[j]);
result.push_back(tmp);
j--;
i++;
}
}
}
return result;
}
};
我仔细检查,没有发现什么问题。我加了一条优化,即被固定的最小数必须是非负数,否则三个数求和不可能为0。但是还是超时。后来,用题目给的测试用例人工跑了一下,发现结果不对,结果含有重复的组。当输入序列中含有重复元素的时候,就很容易出现重复的三个数求和为0的组。
为了解决重复数的问题,在每次指针要发生移动的时候,我都用循环来跳过已经重复过的数。于是就AC了。
代码二:
class Solution {
public:
vector<vector<int> > threeSum(vector<int> &num) {
int n = num.size();
vector<vector<int> > result;
vector<int> tmp;
sort(num.begin(), num.end());
int k, i, j, cur;
k=0;
while(k<n-2 && num[k] <= 0)
{
i = k+1;
j = n-1;
while(i<j)
{
cur = num[i] + num[j] + num[k];
if(cur == 0)
{
tmp.clear();
tmp.push_back(num[k]);
tmp.push_back(num[i]);
tmp.push_back(num[j]);
result.push_back(tmp);
while(num[j] == num[j-1])
j--;
j--;
while(num[i] == num[i+1])
i++;
i++;
}
else if(cur > 0)
{
while(num[j] == num[j-1])
j--;
j--;
}
else
{
while(num[i] == num[i+1])
i++;
i++;
}
}
while(num[k] == num[k+1])
k++;
k++;
}
return result;
}
};