【方法一】
「思路」
将结果总体分为3种:
1.包含0
a.包含一个0
b.3个都是0
2.两正一负
3.两负一正
按照零正负将数组分为三组,依次两两组合两正之和来查看有没有绝对值相等的负数,两负数同理。最后将返回的vector去重。(注意:两正一负,两负一正在返回结果时要注意三个数字的顺序,否则会影响去重结果)
**「结果」**Runtime: 299 ms
「代码」
vector<vector<int>> threeSum(vector<int>& nums)
{
vector<vector<int>>ret;
vector<int> ans(3);
int n=nums.size();
if(n>0){
int p,z,na;
p=z=na=0;
int po[n],nage[n];
map<int,int> positive,zero,nagetive;
/*分组: 正 0 负*/
for(int i=0;i<n;i++)
{
if(nums[i]>0)
{
positive.insert(pair<int, int>(nums[i],p));
po[p]=nums[i];
p++;
}
else if(nums[i]==0)
{
zero.insert(pair<int, int>(nums[i],z));
z++;
}
else
{
nagetive.insert(pair<int, int>(nums[i],na));
nage[na]=nums[i];
na++;
}
}
/*两负一正*/
if(na>=2)
{
for(int i=0;i<na-1;i++)
{
for(int j=i+1;j<na;j++)
{
if(positive.count(abs(nage[i]+nage[j])))
{
ans[2]=abs(nage[i]+nage[j]);
if(nage[j]>nage[i])
{
ans[0]=nage[i];
ans[1]=nage[j];
}
else
{
ans[0]=nage[j];
ans[1]=nage[i];
}
ret.push_back(ans);
}
}
}
}
/*两正一负*/
if(p>=2)
{
for(int i=0;i<p-1;i++)
{
for(int j=i+1;j<p;j++)
{
if(nagetive.count(-(po[i]+po[j])))
{
ans[0]=-(po[i]+po[j]);
if(po[j]>po[i])
{
ans[1]=po[i];
ans[2]=po[j];
}
else
{
ans[1]=po[j];
ans[2]=po[i];
}
ret.push_back(ans);
}
}
}
}
/*带0*/
if(z>0)
{
for(int i=0;i<na;i++)
{
if(positive.count(abs(nage[i])))
{
ans[0]=nage[i];
ans[1]=0;
ans[2]=abs(nage[i]);
ret.push_back(ans);
}
}
if(z>=3)
{
ans[0]=0;
ans[1]=0;
ans[2]=0;
ret.push_back(ans);
}
}
}
sort(ret.begin(),ret.end());
ret.erase(unique(ret.begin(), ret.end()), ret.end());
return ret;
}
【方法二】
「思路」
先将nums数组由大到小排序,一次将数组中的每一个数当作目标数,寻找另外两个数字。另外两个数字相加,当结果大时second向左移一个,当结果小时first向右移一个。
「结果」
Runtime: 122 ms
「代码」
vector<vector<int>> threeSum(vector<int>& nums)
{
vector<vector<int>>ret;
vector<int> ans(3);
int n=nums.size();
sort(nums.begin(),nums.end());
for(int i=0;i<n;i++)
{
int target=-nums[i];
int first=i+1;
int second=n-1;
while(first<second)
{
int sum=nums[first]+nums[second];
if(target==sum)
{
ans[0]=nums[i];
ans[1]=nums[first];
ans[2]=nums[second];
ret.push_back(ans);
first++;
while(first<second && ans[1]==nums[first])
{
first++;
}
}
else if(target<sum)
{
second--;
}
else
{
first++;
}
}
}
sort(ret.begin(),ret.end());
ret.erase(unique(ret.begin(), ret.end()), ret.end());
return ret;
}
leetcode上时间更短的算法大致思想都和方法二类似,都采用了左右夹击的方式。