leetcode上的原题,美图的笔试题目。
本质上这个问题是2数之和的问题扩展:
在给定的数组中找出两个数a,b,使得a+b=sum。
三个数之和为0,即a+b+c=0,可以转化为a+b=-c,这需要保证-c在数组中。下面代码采用了两个循环,第一个循环代表初始值,即先是第一个值a[0]不变,计算a[0]+a[1]+a[n-1],若大于0则k减1,计算a[0]+a[1]+a[n-2],若小于0则j加1,计算a[0]+a[2]+a[n-1]...如果存在多个重复值,这可能会加入重复的数对,不过使用容器set可以解决该问题,相同的数对不会出现在set中。
set<vector<int>> find_triplets(vector<int> arr)
{
sort(arr.begin(), arr.end());
set<vector<int>>ret;
vector<int>temp(3);
int n = arr.size();
for (int i = 0; i < n; ++i)
{
int j = i + 1;
int k = n - 1;
while (j < k)
{
int sum_two = arr[i] + arr[j];
if (sum_two + arr[k] < 0)
++j;
else if (sum_two + arr[k] > 0)
--k;
else
{
temp[0] = arr[i];
temp[1] = arr[j];
temp[2] = arr[k];
ret.insert(temp);
++j;
--k;
}
}
}
return ret;
}
可以不使用容器set去重复,循环时跳过重复相同的数。
vector<vector<int>> find_triples(vector<int>arr)
{
sort(arr.begin(), arr.end());
vector<vector<int>>ret;
int n = arr.size();
for (int i = 0; i < n-2; ++i)
{
if (i == 0 || (i > 0 && arr[i] != arr[i - 1]))
{
int lo = i + 1, hi = n - 1;
int sum = 0 - arr[i];
while (lo < hi)
{
if (arr[lo] + arr[hi] == sum)
{
ret.push_back({ arr[i], arr[lo], arr[hi] });
while (lo < hi && arr[lo] == arr[lo + 1])++lo;//跳过重复值
while (lo < hi && arr[hi] == arr[hi - 1])--hi;
++lo;
--hi;
}
else if (arr[lo] + arr[hi] < sum)
++lo;
else
--hi;
}
}
}
return ret;
}